mirror of
https://github.com/lucaspalomodevelop/netbox-acls.git
synced 2026-03-12 23:27:23 +00:00
lint fixes
This commit is contained in:
parent
df1e3d34f9
commit
41a3f29217
@ -6,7 +6,7 @@
|
||||
|
||||
PLUGINS = [
|
||||
"netbox_access_lists",
|
||||
]
|
||||
]
|
||||
|
||||
PLUGINS_CONFIG = {
|
||||
"netbox_access_lists": {},
|
||||
|
||||
@ -9,4 +9,5 @@ pycodestyle
|
||||
pydocstyle
|
||||
pylint
|
||||
pylint-django
|
||||
wily
|
||||
yapf
|
||||
|
||||
@ -17,7 +17,7 @@ repos:
|
||||
args:
|
||||
- '--py36-plus'
|
||||
- repo: 'https://github.com/asottile/pyupgrade'
|
||||
rev: v2.34.0
|
||||
rev: v2.37.3
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args:
|
||||
@ -42,11 +42,9 @@ repos:
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: 'https://github.com/igorshubovych/markdownlint-cli'
|
||||
rev: v0.31.1
|
||||
rev: v0.32.1
|
||||
hooks:
|
||||
- id: markdownlint
|
||||
- repo: local
|
||||
hooks:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: wily
|
||||
|
||||
@ -6,10 +6,11 @@ from extras.plugins import PluginConfig
|
||||
|
||||
|
||||
class NetBoxAccessListsConfig(PluginConfig):
|
||||
name = 'netbox_access_lists'
|
||||
verbose_name = 'Access Lists'
|
||||
description = 'Manage simple ACLs in NetBox'
|
||||
version = '0.1'
|
||||
base_url = 'access-lists'
|
||||
name = "netbox_access_lists"
|
||||
verbose_name = "Access Lists"
|
||||
description = "Manage simple ACLs in NetBox"
|
||||
version = "0.1"
|
||||
base_url = "access-lists"
|
||||
|
||||
|
||||
config = NetBoxAccessListsConfig
|
||||
|
||||
@ -6,75 +6,88 @@ while Django itself handles the database abstraction.
|
||||
from netbox.api.serializers import WritableNestedSerializer
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models import (AccessList, ACLExtendedRule, ACLInterfaceAssignment,
|
||||
ACLStandardRule)
|
||||
from ..models import (
|
||||
AccessList,
|
||||
ACLExtendedRule,
|
||||
ACLInterfaceAssignment,
|
||||
ACLStandardRule,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'NestedAccessListSerializer',
|
||||
'NestedACLInterfaceAssignmentSerializer',
|
||||
'NestedACLStandardRuleSerializer',
|
||||
'NestedACLExtendedRuleSerializer'
|
||||
"NestedAccessListSerializer",
|
||||
"NestedACLInterfaceAssignmentSerializer",
|
||||
"NestedACLStandardRuleSerializer",
|
||||
"NestedACLExtendedRuleSerializer",
|
||||
]
|
||||
|
||||
|
||||
class NestedAccessListSerializer(WritableNestedSerializer):
|
||||
"""
|
||||
Defines the nested serializer for the django AccessList model & associates it to a view.
|
||||
"""
|
||||
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name='plugins-api:netbox_access_lists-api:accesslist-detail'
|
||||
view_name="plugins-api:netbox_access_lists-api:accesslist-detail",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Associates the django model ACLStandardRule & fields to the nested serializer.
|
||||
"""
|
||||
|
||||
model = AccessList
|
||||
fields = ('id', 'url', 'display', 'name')
|
||||
fields = ("id", "url", "display", "name")
|
||||
|
||||
|
||||
class NestedACLInterfaceAssignmentSerializer(WritableNestedSerializer):
|
||||
"""
|
||||
Defines the nested serializer for the django ACLInterfaceAssignment model & associates it to a view.
|
||||
"""
|
||||
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name='plugins-api:netbox_access_lists-api:aclinterfaceassignment-detail'
|
||||
view_name="plugins-api:netbox_access_lists-api:aclinterfaceassignment-detail",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Associates the django model ACLInterfaceAssignment & fields to the nested serializer.
|
||||
"""
|
||||
|
||||
model = ACLInterfaceAssignment
|
||||
fields = ('id', 'url', 'display', 'access_list')
|
||||
fields = ("id", "url", "display", "access_list")
|
||||
|
||||
|
||||
class NestedACLStandardRuleSerializer(WritableNestedSerializer):
|
||||
"""
|
||||
Defines the nested serializer for the django ACLStandardRule model & associates it to a view.
|
||||
"""
|
||||
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name='plugins-api:netbox_access_lists-api:aclstandardrule-detail'
|
||||
view_name="plugins-api:netbox_access_lists-api:aclstandardrule-detail",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Associates the django model ACLStandardRule & fields to the nested serializer.
|
||||
"""
|
||||
|
||||
model = ACLStandardRule
|
||||
fields = ('id', 'url', 'display', 'index')
|
||||
fields = ("id", "url", "display", "index")
|
||||
|
||||
|
||||
class NestedACLExtendedRuleSerializer(WritableNestedSerializer):
|
||||
"""
|
||||
Defines the nested serializer for the django ACLExtendedRule model & associates it to a view.
|
||||
"""
|
||||
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name='plugins-api:netbox_access_lists-api:aclextendedrule-detail'
|
||||
view_name="plugins-api:netbox_access_lists-api:aclextendedrule-detail",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Associates the django model ACLExtendedRule & fields to the nested serializer.
|
||||
"""
|
||||
|
||||
model = ACLExtendedRule
|
||||
fields = ('id', 'url', 'display', 'index')
|
||||
fields = ("id", "url", "display", "index")
|
||||
|
||||
@ -4,50 +4,60 @@ while Django itself handles the database abstraction.
|
||||
"""
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from drf_yasg.utils import swagger_serializer_method
|
||||
from ipam.api.serializers import NestedPrefixSerializer
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from netbox.api import ContentTypeField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from rest_framework import serializers
|
||||
from utilities.api import get_serializer_for_model
|
||||
|
||||
from ..constants import (ACL_HOST_ASSIGNMENT_MODELS,
|
||||
ACL_INTERFACE_ASSIGNMENT_MODELS)
|
||||
from ..models import (AccessList, ACLExtendedRule, ACLInterfaceAssignment,
|
||||
ACLStandardRule)
|
||||
from .nested_serializers import (NestedAccessListSerializer,
|
||||
from ..constants import ACL_HOST_ASSIGNMENT_MODELS, ACL_INTERFACE_ASSIGNMENT_MODELS
|
||||
from ..models import (
|
||||
AccessList,
|
||||
ACLExtendedRule,
|
||||
ACLInterfaceAssignment,
|
||||
ACLStandardRule,
|
||||
)
|
||||
from .nested_serializers import (
|
||||
NestedAccessListSerializer,
|
||||
NestedACLExtendedRuleSerializer,
|
||||
NestedACLInterfaceAssignmentSerializer,
|
||||
NestedACLStandardRuleSerializer)
|
||||
NestedACLStandardRuleSerializer,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'AccessListSerializer',
|
||||
'ACLInterfaceAssignmentSerializer',
|
||||
'ACLStandardRuleSerializer',
|
||||
'ACLExtendedRuleSerializer'
|
||||
"AccessListSerializer",
|
||||
"ACLInterfaceAssignmentSerializer",
|
||||
"ACLStandardRuleSerializer",
|
||||
"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.'
|
||||
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.'
|
||||
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 not set to remark, but no remark is set.
|
||||
error_message_remark_without_action_remark = 'CANNOT set remark unless action is set to remark.'
|
||||
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.'
|
||||
error_message_acl_type = "Provided parent Access List is not of right type."
|
||||
|
||||
|
||||
class AccessListSerializer(NetBoxModelSerializer):
|
||||
"""
|
||||
Defines the serializer for the django AccessList model & associates it to a view.
|
||||
"""
|
||||
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name='plugins-api:netbox_access_lists-api:accesslist-detail'
|
||||
view_name="plugins-api:netbox_access_lists-api:accesslist-detail",
|
||||
)
|
||||
rule_count = serializers.IntegerField(read_only=True)
|
||||
assigned_object_type = ContentTypeField(
|
||||
queryset=ContentType.objects.filter(ACL_HOST_ASSIGNMENT_MODELS)
|
||||
queryset=ContentType.objects.filter(ACL_HOST_ASSIGNMENT_MODELS),
|
||||
)
|
||||
assigned_object = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
@ -55,16 +65,30 @@ class AccessListSerializer(NetBoxModelSerializer):
|
||||
"""
|
||||
Associates the django model AccessList & fields to the serializer.
|
||||
"""
|
||||
|
||||
model = AccessList
|
||||
fields = (
|
||||
'id', 'url', 'display', 'name', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'type', 'default_action', 'comments', 'tags', 'custom_fields', 'created',
|
||||
'last_updated', 'rule_count'
|
||||
"id",
|
||||
"url",
|
||||
"display",
|
||||
"name",
|
||||
"assigned_object_type",
|
||||
"assigned_object_id",
|
||||
"assigned_object",
|
||||
"type",
|
||||
"default_action",
|
||||
"comments",
|
||||
"tags",
|
||||
"custom_fields",
|
||||
"created",
|
||||
"last_updated",
|
||||
"rule_count",
|
||||
)
|
||||
|
||||
@swagger_serializer_method(serializer_or_field=serializers.DictField)
|
||||
def get_assigned_object(self, obj):
|
||||
serializer = get_serializer_for_model(obj.assigned_object, prefix='Nested')
|
||||
context = {'request': self.context['request']}
|
||||
serializer = get_serializer_for_model(obj.assigned_object, prefix="Nested")
|
||||
context = {"request": self.context["request"]}
|
||||
return serializer(obj.assigned_object, context=context).data
|
||||
|
||||
def validate(self, data):
|
||||
@ -76,18 +100,26 @@ class AccessListSerializer(NetBoxModelSerializer):
|
||||
error_message = {}
|
||||
|
||||
# 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:
|
||||
try:
|
||||
assigned_object = data['assigned_object_type'].get_object_for_this_type(id=data['assigned_object_id'])
|
||||
assigned_object = data["assigned_object_type"].get_object_for_this_type(
|
||||
id=data["assigned_object_id"]
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
# Sets a standard error message for invalid GFK
|
||||
error_message_invalid_gfk = f"Invalid assigned_object {data['assigned_object_type']} ID {data['assigned_object_id']}"
|
||||
error_message['assigned_object_type'] = [error_message_invalid_gfk]
|
||||
error_message['assigned_object_id'] = [error_message_invalid_gfk]
|
||||
error_message["assigned_object_type"] = [error_message_invalid_gfk]
|
||||
error_message["assigned_object_id"] = [error_message_invalid_gfk]
|
||||
|
||||
# Check if Access List has no existing rules before change the Access List's type.
|
||||
if self.instance and self.instance.type != data.get('type') and self.instance.rule_count > 0:
|
||||
error_message['type'] = ['This ACL has ACL rules associated, CANNOT change ACL type.']
|
||||
if (
|
||||
self.instance
|
||||
and self.instance.type != data.get("type")
|
||||
and self.instance.rule_count > 0
|
||||
):
|
||||
error_message["type"] = [
|
||||
"This ACL has ACL rules associated, CANNOT change ACL type."
|
||||
]
|
||||
|
||||
if error_message:
|
||||
raise serializers.ValidationError(error_message)
|
||||
@ -99,11 +131,12 @@ class ACLInterfaceAssignmentSerializer(NetBoxModelSerializer):
|
||||
"""
|
||||
Defines the serializer for the django ACLInterfaceAssignment model & associates it to a view.
|
||||
"""
|
||||
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name='plugins-api:netbox_access_lists-api:aclinterfaceassignment-detail'
|
||||
view_name="plugins-api:netbox_access_lists-api:aclinterfaceassignment-detail",
|
||||
)
|
||||
assigned_object_type = ContentTypeField(
|
||||
queryset=ContentType.objects.filter(ACL_INTERFACE_ASSIGNMENT_MODELS)
|
||||
queryset=ContentType.objects.filter(ACL_INTERFACE_ASSIGNMENT_MODELS),
|
||||
)
|
||||
assigned_object = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
@ -111,16 +144,27 @@ class ACLInterfaceAssignmentSerializer(NetBoxModelSerializer):
|
||||
"""
|
||||
Associates the django model ACLInterfaceAssignment & fields to the serializer.
|
||||
"""
|
||||
|
||||
model = ACLInterfaceAssignment
|
||||
fields = (
|
||||
'id', 'url', 'access_list', 'direction', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'comments', 'tags', 'custom_fields', 'created',
|
||||
'last_updated'
|
||||
"id",
|
||||
"url",
|
||||
"access_list",
|
||||
"direction",
|
||||
"assigned_object_type",
|
||||
"assigned_object_id",
|
||||
"assigned_object",
|
||||
"comments",
|
||||
"tags",
|
||||
"custom_fields",
|
||||
"created",
|
||||
"last_updated",
|
||||
)
|
||||
|
||||
@swagger_serializer_method(serializer_or_field=serializers.DictField)
|
||||
def get_assigned_object(self, obj):
|
||||
serializer = get_serializer_for_model(obj.assigned_object, prefix='Nested')
|
||||
context = {'request': self.context['request']}
|
||||
serializer = get_serializer_for_model(obj.assigned_object, prefix="Nested")
|
||||
context = {"request": self.context["request"]}
|
||||
return serializer(obj.assigned_object, context=context).data
|
||||
|
||||
def validate(self, data):
|
||||
@ -130,56 +174,81 @@ class ACLInterfaceAssignmentSerializer(NetBoxModelSerializer):
|
||||
- Check that the associated interface's parent host has the selected ACL defined.
|
||||
"""
|
||||
error_message = {}
|
||||
acl_host = data['access_list'].assigned_object
|
||||
acl_host = data["access_list"].assigned_object
|
||||
|
||||
# Check that the GFK object is vlaid.
|
||||
if 'assigned_object_type' in data and 'assigned_object_id' in data:
|
||||
if "assigned_object_type" in data and "assigned_object_id" in data:
|
||||
try:
|
||||
assigned_object = data['assigned_object_type'].get_object_for_this_type(id=data['assigned_object_id'])
|
||||
assigned_object = data["assigned_object_type"].get_object_for_this_type(
|
||||
id=data["assigned_object_id"]
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
# Sets a standard error message for invalid GFK
|
||||
error_message_invalid_gfk = f"Invalid assigned_object {data['assigned_object_type']} ID {data['assigned_object_id']}"
|
||||
error_message['assigned_object_type'] = [error_message_invalid_gfk]
|
||||
error_message['assigned_object_id'] = [error_message_invalid_gfk]
|
||||
error_message["assigned_object_type"] = [error_message_invalid_gfk]
|
||||
error_message["assigned_object_id"] = [error_message_invalid_gfk]
|
||||
|
||||
|
||||
if data['assigned_object_type'].model == 'interface':
|
||||
interface_host = data['assigned_object_type'].get_object_for_this_type(id=data['assigned_object_id']).device
|
||||
elif data['assigned_object_type'].model == 'vminterface':
|
||||
interface_host = data['assigned_object_type'].get_object_for_this_type(id=data['assigned_object_id']).virtual_machine
|
||||
if data["assigned_object_type"].model == "interface":
|
||||
interface_host = (
|
||||
data["assigned_object_type"]
|
||||
.get_object_for_this_type(id=data["assigned_object_id"])
|
||||
.device
|
||||
)
|
||||
elif data["assigned_object_type"].model == "vminterface":
|
||||
interface_host = (
|
||||
data["assigned_object_type"]
|
||||
.get_object_for_this_type(id=data["assigned_object_id"])
|
||||
.virtual_machine
|
||||
)
|
||||
# Check that the associated interface's parent host has the selected ACL defined.
|
||||
if acl_host != interface_host:
|
||||
error_acl_not_assigned_to_host = "Access List not present on the selected interface's host."
|
||||
error_message['access_list'] = [error_acl_not_assigned_to_host]
|
||||
error_message['assigned_object_id'] = [error_acl_not_assigned_to_host]
|
||||
error_acl_not_assigned_to_host = (
|
||||
"Access List not present on the selected interface's host."
|
||||
)
|
||||
error_message["access_list"] = [error_acl_not_assigned_to_host]
|
||||
error_message["assigned_object_id"] = [error_acl_not_assigned_to_host]
|
||||
|
||||
if error_message:
|
||||
raise serializers.ValidationError(error_message)
|
||||
|
||||
return super().validate(data)
|
||||
|
||||
|
||||
class ACLStandardRuleSerializer(NetBoxModelSerializer):
|
||||
"""
|
||||
Defines the serializer for the django ACLStandardRule model & associates it to a view.
|
||||
"""
|
||||
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name='plugins-api:netbox_access_lists-api:aclstandardrule-detail'
|
||||
view_name="plugins-api:netbox_access_lists-api:aclstandardrule-detail",
|
||||
)
|
||||
access_list = NestedAccessListSerializer()
|
||||
source_prefix = NestedPrefixSerializer(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
default=None
|
||||
default=None,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Associates the django model ACLStandardRule & fields to the serializer.
|
||||
"""
|
||||
|
||||
model = ACLStandardRule
|
||||
fields = (
|
||||
'id', 'url', 'display', 'access_list', 'index', 'action', 'tags', 'description',
|
||||
'remark', 'created', 'custom_fields', 'last_updated', 'source_prefix'
|
||||
"id",
|
||||
"url",
|
||||
"display",
|
||||
"access_list",
|
||||
"index",
|
||||
"action",
|
||||
"tags",
|
||||
"description",
|
||||
"remark",
|
||||
"created",
|
||||
"custom_fields",
|
||||
"last_updated",
|
||||
"source_prefix",
|
||||
)
|
||||
|
||||
def validate(self, data):
|
||||
@ -191,11 +260,13 @@ class ACLStandardRuleSerializer(NetBoxModelSerializer):
|
||||
error_message = {}
|
||||
|
||||
# Check if action set to remark, but no remark set.
|
||||
if data.get('action') == 'remark' and data.get('remark') is None:
|
||||
error_message['remark'] = [error_message_no_remark]
|
||||
if data.get("action") == "remark" and 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]
|
||||
if data.get("source_prefix"):
|
||||
error_message["source_prefix"] = [
|
||||
error_message_action_remark_source_prefix_set
|
||||
]
|
||||
|
||||
if error_message:
|
||||
raise serializers.ValidationError(error_message)
|
||||
@ -207,30 +278,46 @@ class ACLExtendedRuleSerializer(NetBoxModelSerializer):
|
||||
"""
|
||||
Defines the serializer for the django ACLExtendedRule model & associates it to a view.
|
||||
"""
|
||||
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name='plugins-api:netbox_access_lists-api:aclextendedrule-detail'
|
||||
view_name="plugins-api:netbox_access_lists-api:aclextendedrule-detail",
|
||||
)
|
||||
access_list = NestedAccessListSerializer()
|
||||
source_prefix = NestedPrefixSerializer(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
default=None
|
||||
default=None,
|
||||
)
|
||||
destination_prefix = NestedPrefixSerializer(
|
||||
required=False,
|
||||
allow_null=True,
|
||||
default=None
|
||||
default=None,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Associates the django model ACLExtendedRule & fields to the serializer.
|
||||
"""
|
||||
|
||||
model = ACLExtendedRule
|
||||
fields = (
|
||||
'id', 'url', 'display', 'access_list', 'index', 'action', 'tags', 'description',
|
||||
'created', 'custom_fields', 'last_updated', 'source_prefix', 'source_ports',
|
||||
'destination_prefix', 'destination_ports', 'protocol', 'remark',
|
||||
"id",
|
||||
"url",
|
||||
"display",
|
||||
"access_list",
|
||||
"index",
|
||||
"action",
|
||||
"tags",
|
||||
"description",
|
||||
"created",
|
||||
"custom_fields",
|
||||
"last_updated",
|
||||
"source_prefix",
|
||||
"source_ports",
|
||||
"destination_prefix",
|
||||
"destination_ports",
|
||||
"protocol",
|
||||
"remark",
|
||||
)
|
||||
|
||||
def validate(self, data):
|
||||
@ -247,23 +334,33 @@ class ACLExtendedRuleSerializer(NetBoxModelSerializer):
|
||||
error_message = {}
|
||||
|
||||
# Check if action set to remark, but no remark set.
|
||||
if data.get('action') == 'remark' and data.get('remark') is None:
|
||||
error_message['remark'] = [error_message_no_remark]
|
||||
if data.get("action") == "remark" and 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]
|
||||
if data.get("source_prefix"):
|
||||
error_message["source_prefix"] = [
|
||||
error_message_action_remark_source_prefix_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.']
|
||||
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.']
|
||||
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'] = ['Action is set to remark, Destination Ports CANNOT be set.']
|
||||
if data.get("destination_ports"):
|
||||
error_message["destination_ports"] = [
|
||||
"Action is set to remark, Destination Ports CANNOT be set."
|
||||
]
|
||||
# Check if action set to remark, but protocol set.
|
||||
if data.get('protocol'):
|
||||
error_message['protocol'] = ['Action is set to remark, Protocol CANNOT be set.']
|
||||
if data.get("protocol"):
|
||||
error_message["protocol"] = [
|
||||
"Action is set to remark, Protocol CANNOT be set."
|
||||
]
|
||||
|
||||
if error_message:
|
||||
raise serializers.ValidationError(error_message)
|
||||
|
||||
@ -6,12 +6,12 @@ from netbox.api.routers import NetBoxRouter
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = 'netbox_access_list'
|
||||
app_name = "netbox_access_list"
|
||||
|
||||
router = NetBoxRouter()
|
||||
router.register('access-lists', views.AccessListViewSet)
|
||||
router.register('interface-assignments', views.ACLInterfaceAssignmentViewSet)
|
||||
router.register('standard-acl-rules', views.ACLStandardRuleViewSet)
|
||||
router.register('extended-acl-rules', views.ACLExtendedRuleViewSet)
|
||||
router.register("access-lists", views.AccessListViewSet)
|
||||
router.register("interface-assignments", views.ACLInterfaceAssignmentViewSet)
|
||||
router.register("standard-acl-rules", views.ACLStandardRuleViewSet)
|
||||
router.register("extended-acl-rules", views.ACLExtendedRuleViewSet)
|
||||
|
||||
urlpatterns = router.urls
|
||||
|
||||
@ -8,15 +8,17 @@ from django.db.models import Count
|
||||
from netbox.api.viewsets import NetBoxModelViewSet
|
||||
|
||||
from .. import filtersets, models
|
||||
from .serializers import (AccessListSerializer, ACLExtendedRuleSerializer,
|
||||
from .serializers import (
|
||||
AccessListSerializer,
|
||||
ACLExtendedRuleSerializer,
|
||||
ACLInterfaceAssignmentSerializer,
|
||||
ACLStandardRuleSerializer)
|
||||
ACLStandardRuleSerializer,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'AccessListViewSet',
|
||||
'ACLStandardRuleViewSet',
|
||||
'ACLInterfaceAssignmentViewSet'
|
||||
'ACLExtendedRuleViewSet',
|
||||
"AccessListViewSet",
|
||||
"ACLStandardRuleViewSet",
|
||||
"ACLInterfaceAssignmentViewSet" "ACLExtendedRuleViewSet",
|
||||
]
|
||||
|
||||
|
||||
@ -24,8 +26,9 @@ class AccessListViewSet(NetBoxModelViewSet):
|
||||
"""
|
||||
Defines the view set for the django AccessList model & associates it to a view.
|
||||
"""
|
||||
queryset = models.AccessList.objects.prefetch_related('tags').annotate(
|
||||
rule_count=Count('aclextendedrules') + Count('aclstandardrules')
|
||||
|
||||
queryset = models.AccessList.objects.prefetch_related("tags").annotate(
|
||||
rule_count=Count("aclextendedrules") + Count("aclstandardrules"),
|
||||
)
|
||||
serializer_class = AccessListSerializer
|
||||
filterset_class = filtersets.AccessListFilterSet
|
||||
@ -35,7 +38,10 @@ class ACLInterfaceAssignmentViewSet(NetBoxModelViewSet):
|
||||
"""
|
||||
Defines the view set for the django ACLInterfaceAssignment model & associates it to a view.
|
||||
"""
|
||||
queryset = models.ACLInterfaceAssignment.objects.prefetch_related('access_list', 'tags')
|
||||
|
||||
queryset = models.ACLInterfaceAssignment.objects.prefetch_related(
|
||||
"access_list", "tags"
|
||||
)
|
||||
serializer_class = ACLInterfaceAssignmentSerializer
|
||||
filterset_class = filtersets.ACLInterfaceAssignmentFilterSet
|
||||
|
||||
@ -44,8 +50,11 @@ class ACLStandardRuleViewSet(NetBoxModelViewSet):
|
||||
"""
|
||||
Defines the view set for the django ACLStandardRule model & associates it to a view.
|
||||
"""
|
||||
|
||||
queryset = models.ACLStandardRule.objects.prefetch_related(
|
||||
'access_list', 'tags', 'source_prefix'
|
||||
"access_list",
|
||||
"tags",
|
||||
"source_prefix",
|
||||
)
|
||||
serializer_class = ACLStandardRuleSerializer
|
||||
filterset_class = filtersets.ACLStandardRuleFilterSet
|
||||
@ -55,8 +64,12 @@ class ACLExtendedRuleViewSet(NetBoxModelViewSet):
|
||||
"""
|
||||
Defines the view set for the django ACLExtendedRule model & associates it to a view.
|
||||
"""
|
||||
|
||||
queryset = models.ACLExtendedRule.objects.prefetch_related(
|
||||
'access_list', 'tags', 'source_prefix', 'destination_prefix',
|
||||
"access_list",
|
||||
"tags",
|
||||
"source_prefix",
|
||||
"destination_prefix",
|
||||
)
|
||||
serializer_class = ACLExtendedRuleSerializer
|
||||
filterset_class = filtersets.ACLExtendedRuleFilterSet
|
||||
|
||||
@ -5,12 +5,12 @@ Defines the various choices to be used by the models, forms, and other plugin sp
|
||||
from utilities.choices import ChoiceSet
|
||||
|
||||
__all__ = (
|
||||
'ACLActionChoices',
|
||||
'ACLAssignmentDirectionChoices',
|
||||
'ACLProtocolChoices',
|
||||
'ACLRuleActionChoices',
|
||||
'ACLTypeChoices',
|
||||
'ACLProtocolChoices',
|
||||
"ACLActionChoices",
|
||||
"ACLAssignmentDirectionChoices",
|
||||
"ACLProtocolChoices",
|
||||
"ACLRuleActionChoices",
|
||||
"ACLTypeChoices",
|
||||
"ACLProtocolChoices",
|
||||
)
|
||||
|
||||
|
||||
@ -18,14 +18,15 @@ class ACLActionChoices(ChoiceSet):
|
||||
"""
|
||||
Defines the choices availble for the Access Lists plugin specific to ACL default_action.
|
||||
"""
|
||||
ACTION_DENY = 'deny'
|
||||
ACTION_PERMIT = 'permit'
|
||||
ACTION_REJECT = 'reject'
|
||||
|
||||
ACTION_DENY = "deny"
|
||||
ACTION_PERMIT = "permit"
|
||||
ACTION_REJECT = "reject"
|
||||
|
||||
CHOICES = [
|
||||
(ACTION_DENY, 'Deny', 'red'),
|
||||
(ACTION_PERMIT, 'Permit', 'green'),
|
||||
(ACTION_REJECT, 'Reject (Reset)', 'orange'),
|
||||
(ACTION_DENY, "Deny", "red"),
|
||||
(ACTION_PERMIT, "Permit", "green"),
|
||||
(ACTION_REJECT, "Reject (Reset)", "orange"),
|
||||
]
|
||||
|
||||
|
||||
@ -33,14 +34,15 @@ class ACLRuleActionChoices(ChoiceSet):
|
||||
"""
|
||||
Defines the choices availble for the Access Lists plugin specific to ACL rule actions.
|
||||
"""
|
||||
ACTION_DENY = 'deny'
|
||||
ACTION_PERMIT = 'permit'
|
||||
ACTION_REMARK = 'remark'
|
||||
|
||||
ACTION_DENY = "deny"
|
||||
ACTION_PERMIT = "permit"
|
||||
ACTION_REMARK = "remark"
|
||||
|
||||
CHOICES = [
|
||||
(ACTION_DENY, 'Deny', 'red'),
|
||||
(ACTION_PERMIT, 'Permit', 'green'),
|
||||
(ACTION_REMARK, 'Remark', 'blue'),
|
||||
(ACTION_DENY, "Deny", "red"),
|
||||
(ACTION_PERMIT, "Permit", "green"),
|
||||
(ACTION_REMARK, "Remark", "blue"),
|
||||
]
|
||||
|
||||
|
||||
@ -50,8 +52,8 @@ class ACLAssignmentDirectionChoices(ChoiceSet):
|
||||
"""
|
||||
|
||||
CHOICES = [
|
||||
('ingress', 'Ingress', 'blue'),
|
||||
('egress', 'Egress', 'purple'),
|
||||
("ingress", "Ingress", "blue"),
|
||||
("egress", "Egress", "purple"),
|
||||
]
|
||||
|
||||
|
||||
@ -59,9 +61,10 @@ class ACLTypeChoices(ChoiceSet):
|
||||
"""
|
||||
Defines the choices availble for the Access Lists plugin specific to ACL type.
|
||||
"""
|
||||
|
||||
CHOICES = [
|
||||
('extended', 'Extended', 'purple'),
|
||||
('standard', 'Standard', 'blue'),
|
||||
("extended", "Extended", "purple"),
|
||||
("standard", "Standard", "blue"),
|
||||
]
|
||||
|
||||
|
||||
@ -69,8 +72,9 @@ class ACLProtocolChoices(ChoiceSet):
|
||||
"""
|
||||
Defines the choices availble for the Access Lists plugin specific to ACL Rule protocol.
|
||||
"""
|
||||
|
||||
CHOICES = [
|
||||
('icmp', 'ICMP', 'purple'),
|
||||
('tcp', 'TCP', 'blue'),
|
||||
('udp', 'UDP', 'orange'),
|
||||
("icmp", "ICMP", "purple"),
|
||||
("tcp", "TCP", "blue"),
|
||||
("udp", "UDP", "orange"),
|
||||
]
|
||||
|
||||
@ -4,12 +4,12 @@ Constants for filters
|
||||
from django.db.models import Q
|
||||
|
||||
ACL_HOST_ASSIGNMENT_MODELS = Q(
|
||||
Q(app_label='dcim', model='device') |
|
||||
Q(app_label='dcim', model='virtualchassis') |
|
||||
Q(app_label='virtualization', model='virtualmachine')
|
||||
Q(app_label="dcim", model="device")
|
||||
| Q(app_label="dcim", model="virtualchassis")
|
||||
| Q(app_label="virtualization", model="virtualmachine"),
|
||||
)
|
||||
|
||||
ACL_INTERFACE_ASSIGNMENT_MODELS = Q(
|
||||
Q(app_label='dcim', model='interface') |
|
||||
Q(app_label='virtualization', model='vminterface')
|
||||
Q(app_label="dcim", model="interface")
|
||||
| Q(app_label="virtualization", model="vminterface"),
|
||||
)
|
||||
@ -10,10 +10,10 @@ from virtualization.models import VirtualMachine, VMInterface
|
||||
from .models import *
|
||||
|
||||
__all__ = (
|
||||
'AccessListFilterSet',
|
||||
'ACLStandardRuleFilterSet',
|
||||
'ACLInterfaceAssignmentFilterSet',
|
||||
'ACLExtendedRuleFilterSet',
|
||||
"AccessListFilterSet",
|
||||
"ACLStandardRuleFilterSet",
|
||||
"ACLInterfaceAssignmentFilterSet",
|
||||
"ACLExtendedRuleFilterSet",
|
||||
)
|
||||
|
||||
|
||||
@ -21,46 +21,60 @@ class AccessListFilterSet(NetBoxModelFilterSet):
|
||||
"""
|
||||
Define the filter set for the django model AccessList.
|
||||
"""
|
||||
|
||||
device = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='device__name',
|
||||
field_name="device__name",
|
||||
queryset=Device.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Device (name)',
|
||||
to_field_name="name",
|
||||
label="Device (name)",
|
||||
)
|
||||
device_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='device',
|
||||
field_name="device",
|
||||
queryset=Device.objects.all(),
|
||||
label='Device (ID)',
|
||||
label="Device (ID)",
|
||||
)
|
||||
virtual_chassis = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_chassis__name',
|
||||
field_name="virtual_chassis__name",
|
||||
queryset=VirtualChassis.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Virtual Chassis (name)',
|
||||
to_field_name="name",
|
||||
label="Virtual Chassis (name)",
|
||||
)
|
||||
virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_chassis',
|
||||
field_name="virtual_chassis",
|
||||
queryset=VirtualChassis.objects.all(),
|
||||
label='Virtual Chassis (ID)',
|
||||
label="Virtual Chassis (ID)",
|
||||
)
|
||||
virtual_machine = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine__name',
|
||||
field_name="virtual_machine__name",
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Virtual Machine (name)',
|
||||
to_field_name="name",
|
||||
label="Virtual Machine (name)",
|
||||
)
|
||||
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='virtual_machine',
|
||||
field_name="virtual_machine",
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
label='Virtual machine (ID)',
|
||||
label="Virtual machine (ID)",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Associates the django model AccessList & fields to the filter set.
|
||||
"""
|
||||
|
||||
model = AccessList
|
||||
fields = ('id', 'name', 'device', 'device_id', 'virtual_chassis', 'virtual_chassis_id', 'virtual_machine', 'virtual_machine_id', 'type', 'default_action', 'comments')
|
||||
fields = (
|
||||
"id",
|
||||
"name",
|
||||
"device",
|
||||
"device_id",
|
||||
"virtual_chassis",
|
||||
"virtual_chassis_id",
|
||||
"virtual_machine",
|
||||
"virtual_machine_id",
|
||||
"type",
|
||||
"default_action",
|
||||
"comments",
|
||||
)
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
"""
|
||||
@ -73,35 +87,45 @@ class ACLInterfaceAssignmentFilterSet(NetBoxModelFilterSet):
|
||||
"""
|
||||
Define the filter set for the django model ACLInterfaceAssignment.
|
||||
"""
|
||||
|
||||
interface = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='interface__name',
|
||||
field_name="interface__name",
|
||||
queryset=Interface.objects.all(),
|
||||
to_field_name='name',
|
||||
label='Interface (name)',
|
||||
to_field_name="name",
|
||||
label="Interface (name)",
|
||||
)
|
||||
interface_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='interface',
|
||||
field_name="interface",
|
||||
queryset=Interface.objects.all(),
|
||||
label='Interface (ID)',
|
||||
label="Interface (ID)",
|
||||
)
|
||||
vminterface = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vminterface__name',
|
||||
field_name="vminterface__name",
|
||||
queryset=VMInterface.objects.all(),
|
||||
to_field_name='name',
|
||||
label='VM Interface (name)',
|
||||
to_field_name="name",
|
||||
label="VM Interface (name)",
|
||||
)
|
||||
vminterface_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='vminterface',
|
||||
field_name="vminterface",
|
||||
queryset=VMInterface.objects.all(),
|
||||
label='VM Interface (ID)',
|
||||
label="VM Interface (ID)",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Associates the django model ACLInterfaceAssignment & fields to the filter set.
|
||||
"""
|
||||
|
||||
model = ACLInterfaceAssignment
|
||||
fields = ('id', 'access_list', 'direction', 'interface', 'interface_id', 'vminterface', 'vminterface_id')
|
||||
fields = (
|
||||
"id",
|
||||
"access_list",
|
||||
"direction",
|
||||
"interface",
|
||||
"interface_id",
|
||||
"vminterface",
|
||||
"vminterface_id",
|
||||
)
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
"""
|
||||
@ -119,8 +143,9 @@ class ACLStandardRuleFilterSet(NetBoxModelFilterSet):
|
||||
"""
|
||||
Associates the django model ACLStandardRule & fields to the filter set.
|
||||
"""
|
||||
|
||||
model = ACLStandardRule
|
||||
fields = ('id', 'access_list', 'index', 'action')
|
||||
fields = ("id", "access_list", "index", "action")
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
"""
|
||||
@ -138,8 +163,9 @@ class ACLExtendedRuleFilterSet(NetBoxModelFilterSet):
|
||||
"""
|
||||
Associates the django model ACLExtendedRule & fields to the filter set.
|
||||
"""
|
||||
|
||||
model = ACLExtendedRule
|
||||
fields = ('id', 'access_list', 'index', 'action', 'protocol')
|
||||
fields = ("id", "access_list", "index", "action", "protocol")
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
"""
|
||||
|
||||
@ -2,13 +2,15 @@
|
||||
Import each of the directory's scripts.
|
||||
"""
|
||||
|
||||
#from .bulk_create import *
|
||||
# from .bulk_create import *
|
||||
from .bulk_edit import *
|
||||
#from .bulk_import import *
|
||||
#from .connections import *
|
||||
|
||||
# from .bulk_import import *
|
||||
# from .connections import *
|
||||
from .filtersets import *
|
||||
#from .formsets import *
|
||||
|
||||
# from .formsets import *
|
||||
from .models import *
|
||||
|
||||
#from .object_create import *
|
||||
#from .object_import import *
|
||||
# from .object_create import *
|
||||
# from .object_import import *
|
||||
|
||||
@ -7,19 +7,23 @@ from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.safestring import mark_safe
|
||||
from netbox.forms import NetBoxModelBulkEditForm
|
||||
from utilities.forms import (ChoiceField, DynamicModelChoiceField,
|
||||
StaticSelect, add_blank_choice)
|
||||
from utilities.forms import (
|
||||
ChoiceField,
|
||||
DynamicModelChoiceField,
|
||||
StaticSelect,
|
||||
add_blank_choice,
|
||||
)
|
||||
from virtualization.models import VirtualMachine
|
||||
|
||||
from ..choices import ACLActionChoices, ACLTypeChoices
|
||||
from ..models import AccessList
|
||||
|
||||
#__all__ = (
|
||||
# __all__ = (
|
||||
# 'AccessListBulkEditForm',
|
||||
#)
|
||||
# )
|
||||
|
||||
|
||||
#class AccessListBulkEditForm(NetBoxModelBulkEditForm):
|
||||
# class AccessListBulkEditForm(NetBoxModelBulkEditForm):
|
||||
# model = AccessList
|
||||
#
|
||||
# region = DynamicModelChoiceField(
|
||||
|
||||
@ -2,27 +2,39 @@
|
||||
Defines each django model's GUI filter/search options.
|
||||
"""
|
||||
|
||||
from dcim.models import (Device, Interface, Region, Site, SiteGroup,
|
||||
VirtualChassis)
|
||||
from dcim.models import Device, Interface, Region, Site, SiteGroup, VirtualChassis
|
||||
from django import forms
|
||||
from ipam.models import Prefix
|
||||
from netbox.forms import NetBoxModelFilterSetForm
|
||||
from utilities.forms import (ChoiceField, DynamicModelChoiceField,
|
||||
StaticSelect, StaticSelectMultiple,
|
||||
TagFilterField, add_blank_choice)
|
||||
from utilities.forms import (
|
||||
ChoiceField,
|
||||
DynamicModelChoiceField,
|
||||
StaticSelect,
|
||||
StaticSelectMultiple,
|
||||
TagFilterField,
|
||||
add_blank_choice,
|
||||
)
|
||||
from virtualization.models import VirtualMachine, VMInterface
|
||||
|
||||
from ..choices import (ACLActionChoices, ACLAssignmentDirectionChoices,
|
||||
ACLProtocolChoices, ACLRuleActionChoices,
|
||||
ACLTypeChoices)
|
||||
from ..models import (AccessList, ACLExtendedRule, ACLInterfaceAssignment,
|
||||
ACLStandardRule)
|
||||
from ..choices import (
|
||||
ACLActionChoices,
|
||||
ACLAssignmentDirectionChoices,
|
||||
ACLProtocolChoices,
|
||||
ACLRuleActionChoices,
|
||||
ACLTypeChoices,
|
||||
)
|
||||
from ..models import (
|
||||
AccessList,
|
||||
ACLExtendedRule,
|
||||
ACLInterfaceAssignment,
|
||||
ACLStandardRule,
|
||||
)
|
||||
|
||||
__all__ = (
|
||||
'AccessListFilterForm',
|
||||
'ACLInterfaceAssignmentFilterForm',
|
||||
'ACLStandardRuleFilterForm',
|
||||
'ACLExtendedRuleFilterForm',
|
||||
"AccessListFilterForm",
|
||||
"ACLInterfaceAssignmentFilterForm",
|
||||
"ACLStandardRuleFilterForm",
|
||||
"ACLExtendedRuleFilterForm",
|
||||
)
|
||||
|
||||
|
||||
@ -30,6 +42,7 @@ class AccessListFilterForm(NetBoxModelFilterSetForm):
|
||||
"""
|
||||
GUI filter form to search the django AccessList model.
|
||||
"""
|
||||
|
||||
model = AccessList
|
||||
region = DynamicModelChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
@ -38,40 +51,40 @@ class AccessListFilterForm(NetBoxModelFilterSetForm):
|
||||
site_group = DynamicModelChoiceField(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
required=False,
|
||||
label='Site Group'
|
||||
label="Site Group",
|
||||
)
|
||||
site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
query_params={
|
||||
'region': '$region',
|
||||
'group_id': '$site_group',
|
||||
'site_id': '$site',
|
||||
"region": "$region",
|
||||
"group_id": "$site_group",
|
||||
"site_id": "$site",
|
||||
},
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
type = ChoiceField(
|
||||
choices=add_blank_choice(ACLTypeChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
initial="",
|
||||
widget=StaticSelect(),
|
||||
)
|
||||
default_action = ChoiceField(
|
||||
choices=add_blank_choice(ACLActionChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
initial="",
|
||||
widget=StaticSelect(),
|
||||
label='Default Action',
|
||||
label="Default Action",
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
fieldsets = (
|
||||
(None, ('q', 'tag')),
|
||||
('Host Details', ('region', 'site_group', 'site', 'device')),
|
||||
('ACL Details', ('type', 'default_action')),
|
||||
(None, ("q", "tag")),
|
||||
("Host Details", ("region", "site_group", "site", "device")),
|
||||
("ACL Details", ("type", "default_action")),
|
||||
)
|
||||
|
||||
|
||||
@ -79,6 +92,7 @@ class ACLInterfaceAssignmentFilterForm(NetBoxModelFilterSetForm):
|
||||
"""
|
||||
GUI filter form to search the django AccessList model.
|
||||
"""
|
||||
|
||||
model = ACLInterfaceAssignment
|
||||
region = DynamicModelChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
@ -87,84 +101,85 @@ class ACLInterfaceAssignmentFilterForm(NetBoxModelFilterSetForm):
|
||||
site_group = DynamicModelChoiceField(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
required=False,
|
||||
label='Site Group'
|
||||
label="Site Group",
|
||||
)
|
||||
site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
query_params={
|
||||
'region': '$region',
|
||||
'group_id': '$site_group',
|
||||
'site_id': '$site',
|
||||
"region": "$region",
|
||||
"group_id": "$site_group",
|
||||
"site_id": "$site",
|
||||
},
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
interface = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
}
|
||||
"device_id": "$device",
|
||||
},
|
||||
)
|
||||
virtual_machine = DynamicModelChoiceField(
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
required=False,
|
||||
label='Virtual Machine',
|
||||
label="Virtual Machine",
|
||||
)
|
||||
vminterface = DynamicModelChoiceField(
|
||||
queryset=VMInterface.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'virtual_machine_id': '$virtual_machine'
|
||||
"virtual_machine_id": "$virtual_machine",
|
||||
},
|
||||
label='Interface'
|
||||
label="Interface",
|
||||
)
|
||||
access_list = DynamicModelChoiceField(
|
||||
queryset=AccessList.objects.all(),
|
||||
query_params={
|
||||
'assigned_object': '$device',
|
||||
"assigned_object": "$device",
|
||||
},
|
||||
label='Access List',
|
||||
label="Access List",
|
||||
)
|
||||
direction = ChoiceField(
|
||||
choices=add_blank_choice(ACLAssignmentDirectionChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
initial="",
|
||||
widget=StaticSelect(),
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
#fieldsets = (
|
||||
# fieldsets = (
|
||||
# (None, ('q', 'tag')),
|
||||
# ('Host Details', ('region', 'site_group', 'site', 'device')),
|
||||
# ('ACL Details', ('type', 'default_action')),
|
||||
#)
|
||||
# )
|
||||
|
||||
|
||||
class ACLStandardRuleFilterForm(NetBoxModelFilterSetForm):
|
||||
"""
|
||||
GUI filter form to search the django ACLStandardRule model.
|
||||
"""
|
||||
|
||||
model = ACLStandardRule
|
||||
tag = TagFilterField(model)
|
||||
source_prefix = forms.ModelMultipleChoiceField(
|
||||
queryset=Prefix.objects.all(),
|
||||
required=False,
|
||||
widget=StaticSelectMultiple(),
|
||||
label='Source Prefix',
|
||||
label="Source Prefix",
|
||||
)
|
||||
action = forms.ChoiceField(
|
||||
choices=add_blank_choice(ACLRuleActionChoices),
|
||||
required=False,
|
||||
initial='',
|
||||
initial="",
|
||||
widget=StaticSelect(),
|
||||
)
|
||||
fieldsets = (
|
||||
(None, ('q', 'tag')),
|
||||
('Rule Details', ('action', 'source_prefix',)),
|
||||
(None, ("q", "tag")),
|
||||
("Rule Details", ("action", "source_prefix")),
|
||||
)
|
||||
|
||||
|
||||
@ -172,37 +187,38 @@ class ACLExtendedRuleFilterForm(NetBoxModelFilterSetForm):
|
||||
"""
|
||||
GUI filter form to search the django ACLExtendedRule model.
|
||||
"""
|
||||
|
||||
model = ACLExtendedRule
|
||||
index = forms.IntegerField(
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
action = forms.ChoiceField(
|
||||
choices=add_blank_choice(ACLRuleActionChoices),
|
||||
required=False,
|
||||
widget=StaticSelect(),
|
||||
initial='',
|
||||
initial="",
|
||||
)
|
||||
source_prefix = forms.ModelMultipleChoiceField(
|
||||
queryset=Prefix.objects.all(),
|
||||
required=False,
|
||||
widget=StaticSelectMultiple(),
|
||||
label='Source Prefix',
|
||||
label="Source Prefix",
|
||||
)
|
||||
desintation_prefix = forms.ModelMultipleChoiceField(
|
||||
queryset=Prefix.objects.all(),
|
||||
required=False,
|
||||
widget=StaticSelectMultiple(),
|
||||
label='Destination Prefix',
|
||||
label="Destination Prefix",
|
||||
)
|
||||
protocol = ChoiceField(
|
||||
choices=add_blank_choice(ACLProtocolChoices),
|
||||
required=False,
|
||||
widget=StaticSelect(),
|
||||
initial='',
|
||||
initial="",
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
(None, ('q', 'tag')),
|
||||
('Rule Details', ('action', 'source_prefix', 'desintation_prefix', 'protocol')),
|
||||
(None, ("q", "tag")),
|
||||
("Rule Details", ("action", "source_prefix", "desintation_prefix", "protocol")),
|
||||
)
|
||||
|
||||
@ -2,41 +2,55 @@
|
||||
Defines each django model's GUI form to add or edit objects for each django model.
|
||||
"""
|
||||
|
||||
from dcim.models import (Device, Interface, Region, Site, SiteGroup,
|
||||
VirtualChassis)
|
||||
from dcim.models import Device, Interface, Region, Site, SiteGroup, VirtualChassis
|
||||
from django import forms
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.safestring import mark_safe
|
||||
from extras.models import Tag
|
||||
from ipam.models import Prefix
|
||||
from netbox.forms import NetBoxModelForm
|
||||
from utilities.forms import (CommentField, DynamicModelChoiceField,
|
||||
DynamicModelMultipleChoiceField)
|
||||
from utilities.forms import (
|
||||
CommentField,
|
||||
DynamicModelChoiceField,
|
||||
DynamicModelMultipleChoiceField,
|
||||
)
|
||||
from virtualization.models import VirtualMachine, VMInterface
|
||||
|
||||
from ..models import (AccessList, ACLExtendedRule, ACLInterfaceAssignment,
|
||||
ACLStandardRule)
|
||||
from ..models import (
|
||||
AccessList,
|
||||
ACLExtendedRule,
|
||||
ACLInterfaceAssignment,
|
||||
ACLStandardRule,
|
||||
)
|
||||
|
||||
__all__ = (
|
||||
'AccessListForm',
|
||||
'ACLInterfaceAssignmentForm',
|
||||
'ACLStandardRuleForm',
|
||||
'ACLExtendedRuleForm',
|
||||
"AccessListForm",
|
||||
"ACLInterfaceAssignmentForm",
|
||||
"ACLStandardRuleForm",
|
||||
"ACLExtendedRuleForm",
|
||||
)
|
||||
|
||||
# Sets a standard mark_safe help_text value to be used by the various classes
|
||||
help_text_acl_rule_logic = mark_safe('<b>*Note:</b> CANNOT be set if action is set to remark.')
|
||||
help_text_acl_rule_logic = mark_safe(
|
||||
"<b>*Note:</b> CANNOT be set if action is set to remark."
|
||||
)
|
||||
# Sets a standard help_text value to be used by the various classes for acl action
|
||||
help_text_acl_action = 'Action the rule will take (remark, deny, or allow).'
|
||||
help_text_acl_action = "Action the rule will take (remark, deny, or allow)."
|
||||
# Sets a standard help_text value to be used by the various classes for acl index
|
||||
help_text_acl_rule_index = 'Determines the order of the rule in the ACL processing. AKA Sequence Number.'
|
||||
help_text_acl_rule_index = (
|
||||
"Determines the order of the rule in the ACL processing. AKA Sequence Number."
|
||||
)
|
||||
|
||||
# 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.'
|
||||
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.'
|
||||
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 not set to remark, but no remark is set.
|
||||
error_message_remark_without_action_remark = 'CANNOT set remark unless action is set to remark.'
|
||||
error_message_remark_without_action_remark = (
|
||||
"CANNOT set remark unless action is set to remark."
|
||||
)
|
||||
|
||||
|
||||
class AccessListForm(NetBoxModelForm):
|
||||
@ -44,6 +58,7 @@ class AccessListForm(NetBoxModelForm):
|
||||
GUI form to add or edit an AccessList.
|
||||
Requires a device, a name, a type, and a default_action.
|
||||
"""
|
||||
|
||||
region = DynamicModelChoiceField(
|
||||
queryset=Region.objects.all(),
|
||||
required=False,
|
||||
@ -51,59 +66,73 @@ class AccessListForm(NetBoxModelForm):
|
||||
site_group = DynamicModelChoiceField(
|
||||
queryset=SiteGroup.objects.all(),
|
||||
required=False,
|
||||
label='Site Group'
|
||||
label="Site Group",
|
||||
)
|
||||
site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'region': '$region',
|
||||
'group_id': '$site_group',
|
||||
'site_id': '$site',
|
||||
"region": "$region",
|
||||
"group_id": "$site_group",
|
||||
"site_id": "$site",
|
||||
},
|
||||
)
|
||||
virtual_chassis = DynamicModelChoiceField(
|
||||
queryset=VirtualChassis.objects.all(),
|
||||
required=False,
|
||||
label='Virtual Chassis',
|
||||
label="Virtual Chassis",
|
||||
)
|
||||
virtual_machine = DynamicModelChoiceField(
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
required=False,
|
||||
label='Virtual Machine',
|
||||
label="Virtual Machine",
|
||||
)
|
||||
comments = CommentField()
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = AccessList
|
||||
fields = ('region', 'site_group', 'site', 'device', 'virtual_machine', 'virtual_chassis', 'name', 'type', 'default_action', 'comments', 'tags')
|
||||
fields = (
|
||||
"region",
|
||||
"site_group",
|
||||
"site",
|
||||
"device",
|
||||
"virtual_machine",
|
||||
"virtual_chassis",
|
||||
"name",
|
||||
"type",
|
||||
"default_action",
|
||||
"comments",
|
||||
"tags",
|
||||
)
|
||||
help_texts = {
|
||||
'default_action': 'The default behavior of the ACL.',
|
||||
'name': 'The name uniqueness per device is case insensitive.',
|
||||
'type': mark_safe('<b>*Note:</b> CANNOT be changed if ACL Rules are assoicated to this Access List.'),
|
||||
"default_action": "The default behavior of the ACL.",
|
||||
"name": "The name uniqueness per device is case insensitive.",
|
||||
"type": mark_safe(
|
||||
"<b>*Note:</b> CANNOT be changed if ACL Rules are assoicated to this Access List."
|
||||
),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
# Initialize helper selectors
|
||||
instance = kwargs.get('instance')
|
||||
initial = kwargs.get('initial', {}).copy()
|
||||
instance = kwargs.get("instance")
|
||||
initial = kwargs.get("initial", {}).copy()
|
||||
if instance:
|
||||
if type(instance.assigned_object) is Device:
|
||||
initial['device'] = instance.assigned_object
|
||||
initial["device"] = instance.assigned_object
|
||||
elif type(instance.assigned_object) is VirtualChassis:
|
||||
initial['virtual_chassis'] = instance.assigned_object
|
||||
initial["virtual_chassis"] = instance.assigned_object
|
||||
elif type(instance.assigned_object) is VirtualMachine:
|
||||
initial['virtual_machine'] = instance.assigned_object
|
||||
kwargs['initial'] = initial
|
||||
initial["virtual_machine"] = instance.assigned_object
|
||||
kwargs["initial"] = initial
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@ -117,40 +146,62 @@ class AccessListForm(NetBoxModelForm):
|
||||
"""
|
||||
cleaned_data = super().clean()
|
||||
error_message = {}
|
||||
if self.errors.get('name'):
|
||||
if self.errors.get("name"):
|
||||
return cleaned_data
|
||||
name = cleaned_data.get('name')
|
||||
acl_type = cleaned_data.get('type')
|
||||
device = cleaned_data.get('device')
|
||||
virtual_chassis = cleaned_data.get('virtual_chassis')
|
||||
virtual_machine = cleaned_data.get('virtual_machine')
|
||||
|
||||
name = cleaned_data.get("name")
|
||||
acl_type = cleaned_data.get("type")
|
||||
device = cleaned_data.get("device")
|
||||
virtual_chassis = cleaned_data.get("virtual_chassis")
|
||||
virtual_machine = cleaned_data.get("virtual_machine")
|
||||
|
||||
# Check if more than one host type selected.
|
||||
if (device and virtual_chassis) or (device and virtual_machine) or (virtual_chassis and virtual_machine):
|
||||
raise forms.ValidationError('Access Lists must be assigned to one host (either a device, virtual chassis or virtual machine) at a time.')
|
||||
if (
|
||||
(device and virtual_chassis)
|
||||
or (device and virtual_machine)
|
||||
or (virtual_chassis and virtual_machine)
|
||||
):
|
||||
raise forms.ValidationError(
|
||||
"Access Lists must be assigned to one host (either a device, virtual chassis or virtual machine) at a time."
|
||||
)
|
||||
# Check if no hosts selected.
|
||||
if not device and not virtual_chassis and not virtual_machine:
|
||||
raise forms.ValidationError('Access Lists must be assigned to a device, virtual chassis or virtual machine.')
|
||||
raise forms.ValidationError(
|
||||
"Access Lists must be assigned to a device, virtual chassis or virtual machine."
|
||||
)
|
||||
|
||||
if device:
|
||||
host_type = 'device'
|
||||
host_type = "device"
|
||||
existing_acls = AccessList.objects.filter(name=name, device=device).exists()
|
||||
elif virtual_chassis:
|
||||
host_type = 'virtual_chassis'
|
||||
existing_acls = AccessList.objects.filter(name=name, virtual_chassis=virtual_chassis).exists()
|
||||
host_type = "virtual_chassis"
|
||||
existing_acls = AccessList.objects.filter(
|
||||
name=name, virtual_chassis=virtual_chassis
|
||||
).exists()
|
||||
elif virtual_machine:
|
||||
host_type = 'virtual_machine'
|
||||
existing_acls = AccessList.objects.filter(name=name, virtual_machine=virtual_machine).exists()
|
||||
host_type = "virtual_machine"
|
||||
existing_acls = AccessList.objects.filter(
|
||||
name=name, virtual_machine=virtual_machine
|
||||
).exists()
|
||||
host = cleaned_data.get(host_type)
|
||||
|
||||
# Check if duplicate entry.
|
||||
if ('name' in self.changed_data or host_type in self.changed_data) and existing_acls:
|
||||
error_same_acl_name = 'An ACL with this name is already associated to this host.'
|
||||
error_message |= {host_type: [error_same_acl_name], 'name': [error_same_acl_name]}
|
||||
if (
|
||||
"name" in self.changed_data or host_type in self.changed_data
|
||||
) and existing_acls:
|
||||
error_same_acl_name = (
|
||||
"An ACL with this name is already associated to this host."
|
||||
)
|
||||
error_message |= {
|
||||
host_type: [error_same_acl_name],
|
||||
"name": [error_same_acl_name],
|
||||
}
|
||||
# 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 (acl_type == 'standard' and self.instance.aclextendedrules.exists()):
|
||||
error_message['type'] = ['This ACL has ACL rules associated, CANNOT change ACL type.']
|
||||
if (acl_type == "extended" and self.instance.aclstandardrules.exists()) or (
|
||||
acl_type == "standard" and self.instance.aclextendedrules.exists()
|
||||
):
|
||||
error_message["type"] = [
|
||||
"This ACL has ACL rules associated, CANNOT change ACL type."
|
||||
]
|
||||
|
||||
if error_message:
|
||||
raise forms.ValidationError(error_message)
|
||||
@ -159,7 +210,11 @@ class AccessListForm(NetBoxModelForm):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# Set assigned object
|
||||
self.instance.assigned_object = self.cleaned_data.get('device') or self.cleaned_data.get('virtual_chassis') or self.cleaned_data.get('virtual_machine')
|
||||
self.instance.assigned_object = (
|
||||
self.cleaned_data.get("device")
|
||||
or self.cleaned_data.get("virtual_chassis")
|
||||
or self.cleaned_data.get("virtual_machine")
|
||||
)
|
||||
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
@ -169,6 +224,7 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
|
||||
GUI form to add or edit ACL Host Object assignments
|
||||
Requires an access_list, a name, a type, and a default_action.
|
||||
"""
|
||||
|
||||
device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
@ -180,67 +236,76 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
|
||||
queryset=Interface.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'device_id': '$device'
|
||||
}
|
||||
"device_id": "$device",
|
||||
},
|
||||
)
|
||||
virtual_machine = DynamicModelChoiceField(
|
||||
queryset=VirtualMachine.objects.all(),
|
||||
required=False,
|
||||
label='Virtual Machine',
|
||||
label="Virtual Machine",
|
||||
)
|
||||
vminterface = DynamicModelChoiceField(
|
||||
queryset=VMInterface.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'virtual_machine_id': '$virtual_machine'
|
||||
"virtual_machine_id": "$virtual_machine",
|
||||
},
|
||||
label='VM Interface'
|
||||
label="VM Interface",
|
||||
)
|
||||
#virtual_chassis = DynamicModelChoiceField(
|
||||
# virtual_chassis = DynamicModelChoiceField(
|
||||
# queryset=VirtualChassis.objects.all(),
|
||||
# required=False,
|
||||
# label='Virtual Chassis',
|
||||
#)
|
||||
# )
|
||||
access_list = DynamicModelChoiceField(
|
||||
queryset=AccessList.objects.all(),
|
||||
#query_params={
|
||||
# query_params={
|
||||
# 'assigned_object': '$device',
|
||||
# 'assigned_object': '$virtual_machine',
|
||||
#},
|
||||
label='Access List',
|
||||
help_text=mark_safe('<b>*Note:</b> Access List must be present on the device already.')
|
||||
# },
|
||||
label="Access List",
|
||||
help_text=mark_safe(
|
||||
"<b>*Note:</b> Access List must be present on the device already."
|
||||
),
|
||||
)
|
||||
comments = CommentField()
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
# Initialize helper selectors
|
||||
instance = kwargs.get('instance')
|
||||
initial = kwargs.get('initial', {}).copy()
|
||||
instance = kwargs.get("instance")
|
||||
initial = kwargs.get("initial", {}).copy()
|
||||
if instance:
|
||||
if type(instance.assigned_object) is Interface:
|
||||
initial['interface'] = instance.assigned_object
|
||||
initial['device'] = 'device'
|
||||
initial["interface"] = instance.assigned_object
|
||||
initial["device"] = "device"
|
||||
elif type(instance.assigned_object) is VMInterface:
|
||||
initial['vminterface'] = instance.assigned_object
|
||||
initial['virtual_machine'] = 'virtual_machine'
|
||||
kwargs['initial'] = initial
|
||||
initial["vminterface"] = instance.assigned_object
|
||||
initial["virtual_machine"] = "virtual_machine"
|
||||
kwargs["initial"] = initial
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class Meta:
|
||||
model = ACLInterfaceAssignment
|
||||
fields = (
|
||||
'access_list', 'direction', 'device', 'interface', 'virtual_machine',
|
||||
'vminterface', 'comments', 'tags',
|
||||
"access_list",
|
||||
"direction",
|
||||
"device",
|
||||
"interface",
|
||||
"virtual_machine",
|
||||
"vminterface",
|
||||
"comments",
|
||||
"tags",
|
||||
)
|
||||
help_texts = {
|
||||
'direction': mark_safe('<b>*Note:</b> CANNOT assign 2 ACLs to the same interface & direction.'),
|
||||
"direction": mark_safe(
|
||||
"<b>*Note:</b> CANNOT assign 2 ACLs to the same interface & direction."
|
||||
),
|
||||
}
|
||||
|
||||
def clean(self):
|
||||
@ -255,47 +320,81 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
|
||||
"""
|
||||
cleaned_data = super().clean()
|
||||
error_message = {}
|
||||
access_list = cleaned_data.get('access_list')
|
||||
direction = cleaned_data.get('direction')
|
||||
interface = cleaned_data.get('interface')
|
||||
vminterface = cleaned_data.get('vminterface')
|
||||
assigned_object = cleaned_data.get('assigned_object')
|
||||
access_list = cleaned_data.get("access_list")
|
||||
direction = cleaned_data.get("direction")
|
||||
interface = cleaned_data.get("interface")
|
||||
vminterface = cleaned_data.get("vminterface")
|
||||
assigned_object = cleaned_data.get("assigned_object")
|
||||
if interface:
|
||||
assigned_object = interface
|
||||
assigned_object_type = 'interface'
|
||||
host_type = 'device'
|
||||
assigned_object_type = "interface"
|
||||
host_type = "device"
|
||||
host = Interface.objects.get(pk=assigned_object.pk).device
|
||||
elif vminterface:
|
||||
assigned_object = vminterface
|
||||
assigned_object_type = 'vminterface'
|
||||
host_type = 'virtual_machine'
|
||||
assigned_object_type = "vminterface"
|
||||
host_type = "virtual_machine"
|
||||
host = VMInterface.objects.get(pk=assigned_object.pk).virtual_machine
|
||||
if interface or vminterface:
|
||||
assigned_object_id = VMInterface.objects.get(pk=assigned_object.pk).pk
|
||||
assigned_object_type_id = ContentType.objects.get_for_model(assigned_object).pk
|
||||
assigned_object_type_id = ContentType.objects.get_for_model(
|
||||
assigned_object
|
||||
).pk
|
||||
access_list_host = AccessList.objects.get(pk=access_list.pk).assigned_object
|
||||
|
||||
# Check if both interface and vminterface are set.
|
||||
if interface and vminterface:
|
||||
error_too_many_interfaces = 'Access Lists must be assigned to one type of interface at a time (VM interface or physical interface)'
|
||||
error_too_many_hosts = 'Access Lists must be assigned to one type of device at a time (VM or physical device).'
|
||||
error_message |= {'device': [error_too_many_hosts], 'interface': [error_too_many_interfaces], 'virtual_machine': [error_too_many_hosts], 'vminterface': [error_too_many_interfaces]}
|
||||
error_too_many_interfaces = "Access Lists must be assigned to one type of interface at a time (VM interface or physical interface)"
|
||||
error_too_many_hosts = "Access Lists must be assigned to one type of device at a time (VM or physical device)."
|
||||
error_message |= {
|
||||
"device": [error_too_many_hosts],
|
||||
"interface": [error_too_many_interfaces],
|
||||
"virtual_machine": [error_too_many_hosts],
|
||||
"vminterface": [error_too_many_interfaces],
|
||||
}
|
||||
# Check if neither interface or vminterface are set.
|
||||
elif not (interface or vminterface):
|
||||
error_no_interface = 'An Access List assignment but specify an Interface or VM Interface.'
|
||||
error_message |= {'interface': [error_no_interface], 'vminterface': [error_no_interface]}
|
||||
error_no_interface = (
|
||||
"An Access List assignment but specify an Interface or VM Interface."
|
||||
)
|
||||
error_message |= {
|
||||
"interface": [error_no_interface],
|
||||
"vminterface": [error_no_interface],
|
||||
}
|
||||
# Check that an interface's parent device/virtual_machine is assigned to the Access List.
|
||||
elif access_list_host != host:
|
||||
error_acl_not_assigned_to_host = 'Access List not present on selected host.'
|
||||
error_message |= {'access_list': [error_acl_not_assigned_to_host], assigned_object_type: [error_acl_not_assigned_to_host], host_type: [error_acl_not_assigned_to_host]}
|
||||
error_acl_not_assigned_to_host = "Access List not present on selected host."
|
||||
error_message |= {
|
||||
"access_list": [error_acl_not_assigned_to_host],
|
||||
assigned_object_type: [error_acl_not_assigned_to_host],
|
||||
host_type: [error_acl_not_assigned_to_host],
|
||||
}
|
||||
# Check for duplicate entry.
|
||||
elif ACLInterfaceAssignment.objects.filter(access_list=access_list, assigned_object_id=assigned_object_id, assigned_object_type=assigned_object_type_id, direction=direction).exists():
|
||||
error_duplicate_entry = 'An ACL with this name is already associated to this interface & direction.'
|
||||
error_message |= {'access_list': [error_duplicate_entry], 'direction': [error_duplicate_entry], assigned_object_type: [error_duplicate_entry]}
|
||||
elif ACLInterfaceAssignment.objects.filter(
|
||||
access_list=access_list,
|
||||
assigned_object_id=assigned_object_id,
|
||||
assigned_object_type=assigned_object_type_id,
|
||||
direction=direction,
|
||||
).exists():
|
||||
error_duplicate_entry = "An ACL with this name is already associated to this interface & direction."
|
||||
error_message |= {
|
||||
"access_list": [error_duplicate_entry],
|
||||
"direction": [error_duplicate_entry],
|
||||
assigned_object_type: [error_duplicate_entry],
|
||||
}
|
||||
# Check that the interface does not have an existing ACL applied in the direction already.
|
||||
elif ACLInterfaceAssignment.objects.filter(assigned_object_id=assigned_object_id, assigned_object_type=assigned_object_type_id, direction=direction).exists():
|
||||
error_interface_already_assigned = 'Interfaces can only have 1 Access List assigned in each direction.'
|
||||
error_message |= {'direction': [error_interface_already_assigned], assigned_object_type: [error_interface_already_assigned]}
|
||||
elif ACLInterfaceAssignment.objects.filter(
|
||||
assigned_object_id=assigned_object_id,
|
||||
assigned_object_type=assigned_object_type_id,
|
||||
direction=direction,
|
||||
).exists():
|
||||
error_interface_already_assigned = (
|
||||
"Interfaces can only have 1 Access List assigned in each direction."
|
||||
)
|
||||
error_message |= {
|
||||
"direction": [error_interface_already_assigned],
|
||||
assigned_object_type: [error_interface_already_assigned],
|
||||
}
|
||||
|
||||
if error_message:
|
||||
raise forms.ValidationError(error_message)
|
||||
@ -303,7 +402,9 @@ class ACLInterfaceAssignmentForm(NetBoxModelForm):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# Set assigned object
|
||||
self.instance.assigned_object = self.cleaned_data.get('interface') or self.cleaned_data.get('vminterface')
|
||||
self.instance.assigned_object = self.cleaned_data.get(
|
||||
"interface"
|
||||
) or self.cleaned_data.get("vminterface")
|
||||
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
@ -314,40 +415,50 @@ class ACLStandardRuleForm(NetBoxModelForm):
|
||||
Requires an access_list, an index, and ACL rule type.
|
||||
See the clean function for logic on other field requirements.
|
||||
"""
|
||||
|
||||
access_list = DynamicModelChoiceField(
|
||||
queryset=AccessList.objects.all(),
|
||||
query_params={
|
||||
'type': 'standard'
|
||||
"type": "standard",
|
||||
},
|
||||
help_text=mark_safe('<b>*Note:</b> This field will only display Standard ACLs.'),
|
||||
label='Access List',
|
||||
help_text=mark_safe(
|
||||
"<b>*Note:</b> This field will only display Standard ACLs."
|
||||
),
|
||||
label="Access List",
|
||||
)
|
||||
source_prefix = DynamicModelChoiceField(
|
||||
queryset=Prefix.objects.all(),
|
||||
required=False,
|
||||
help_text=help_text_acl_rule_logic,
|
||||
label='Source Prefix',
|
||||
label="Source Prefix",
|
||||
)
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
('Access List Details', ('access_list', 'description', 'tags')),
|
||||
('Rule Definition', ('index', 'action', 'remark', 'source_prefix')),
|
||||
("Access List Details", ("access_list", "description", "tags")),
|
||||
("Rule Definition", ("index", "action", "remark", "source_prefix")),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ACLStandardRule
|
||||
fields = (
|
||||
'access_list', 'index', 'action', 'remark', 'source_prefix',
|
||||
'tags', 'description'
|
||||
"access_list",
|
||||
"index",
|
||||
"action",
|
||||
"remark",
|
||||
"source_prefix",
|
||||
"tags",
|
||||
"description",
|
||||
)
|
||||
help_texts = {
|
||||
'index': help_text_acl_rule_index,
|
||||
'action': help_text_acl_action,
|
||||
'remark': mark_safe('<b>*Note:</b> CANNOT be set if source prefix OR action is set.'),
|
||||
"index": help_text_acl_rule_index,
|
||||
"action": help_text_acl_action,
|
||||
"remark": mark_safe(
|
||||
"<b>*Note:</b> CANNOT be set if source prefix OR action is set."
|
||||
),
|
||||
}
|
||||
|
||||
def clean(self):
|
||||
@ -362,16 +473,18 @@ class ACLStandardRuleForm(NetBoxModelForm):
|
||||
|
||||
# No need to check for unique_together since there is no usage of GFK
|
||||
|
||||
if cleaned_data.get('action') == 'remark':
|
||||
if cleaned_data.get("action") == "remark":
|
||||
# Check if action set to remark, but no remark set.
|
||||
if not cleaned_data.get('remark'):
|
||||
error_message['remark'] = [error_message_no_remark]
|
||||
if not cleaned_data.get("remark"):
|
||||
error_message["remark"] = [error_message_no_remark]
|
||||
# Check if action set to remark, but source_prefix set.
|
||||
if cleaned_data.get('source_prefix'):
|
||||
error_message['source_prefix'] = [error_message_action_remark_source_prefix_set]
|
||||
if cleaned_data.get("source_prefix"):
|
||||
error_message["source_prefix"] = [
|
||||
error_message_action_remark_source_prefix_set
|
||||
]
|
||||
# Check remark set, but action not set to remark.
|
||||
elif cleaned_data.get('remark'):
|
||||
error_message['remark'] = [error_message_remark_without_action_remark]
|
||||
elif cleaned_data.get("remark"):
|
||||
error_message["remark"] = [error_message_remark_without_action_remark]
|
||||
|
||||
if error_message:
|
||||
raise forms.ValidationError(error_message)
|
||||
@ -384,49 +497,74 @@ class ACLExtendedRuleForm(NetBoxModelForm):
|
||||
Requires an access_list, an index, and ACL rule type.
|
||||
See the clean function for logic on other field requirements.
|
||||
"""
|
||||
|
||||
access_list = DynamicModelChoiceField(
|
||||
queryset=AccessList.objects.all(),
|
||||
query_params={
|
||||
'type': 'extended'
|
||||
"type": "extended",
|
||||
},
|
||||
help_text=mark_safe('<b>*Note:</b> This field will only display Extended ACLs.'),
|
||||
label='Access List',
|
||||
help_text=mark_safe(
|
||||
"<b>*Note:</b> This field will only display Extended ACLs."
|
||||
),
|
||||
label="Access List",
|
||||
)
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
source_prefix = DynamicModelChoiceField(
|
||||
queryset=Prefix.objects.all(),
|
||||
required=False,
|
||||
help_text=help_text_acl_rule_logic,
|
||||
label='Source Prefix',
|
||||
label="Source Prefix",
|
||||
)
|
||||
destination_prefix = DynamicModelChoiceField(
|
||||
queryset=Prefix.objects.all(),
|
||||
required=False,
|
||||
help_text=help_text_acl_rule_logic,
|
||||
label='Destination Prefix',
|
||||
label="Destination Prefix",
|
||||
)
|
||||
fieldsets = (
|
||||
('Access List Details', ('access_list', 'description', 'tags')),
|
||||
('Rule Definition', ('index', 'action', 'remark', 'source_prefix', 'source_ports', 'destination_prefix', 'destination_ports', 'protocol',)),
|
||||
("Access List Details", ("access_list", "description", "tags")),
|
||||
(
|
||||
"Rule Definition",
|
||||
(
|
||||
"index",
|
||||
"action",
|
||||
"remark",
|
||||
"source_prefix",
|
||||
"source_ports",
|
||||
"destination_prefix",
|
||||
"destination_ports",
|
||||
"protocol",
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ACLExtendedRule
|
||||
fields = (
|
||||
'access_list', 'index', 'action', 'remark', 'source_prefix',
|
||||
'source_ports', 'destination_prefix', 'destination_ports', 'protocol',
|
||||
'tags', 'description'
|
||||
"access_list",
|
||||
"index",
|
||||
"action",
|
||||
"remark",
|
||||
"source_prefix",
|
||||
"source_ports",
|
||||
"destination_prefix",
|
||||
"destination_ports",
|
||||
"protocol",
|
||||
"tags",
|
||||
"description",
|
||||
)
|
||||
help_texts = {
|
||||
'action': help_text_acl_action,
|
||||
'destination_ports': help_text_acl_rule_logic,
|
||||
'index': help_text_acl_rule_index,
|
||||
'protocol': help_text_acl_rule_logic,
|
||||
'remark': mark_safe('<b>*Note:</b> CANNOT be set if action is not set to remark.'),
|
||||
'source_ports': help_text_acl_rule_logic,
|
||||
"action": help_text_acl_action,
|
||||
"destination_ports": help_text_acl_rule_logic,
|
||||
"index": help_text_acl_rule_index,
|
||||
"protocol": help_text_acl_rule_logic,
|
||||
"remark": mark_safe(
|
||||
"<b>*Note:</b> CANNOT be set if action is not set to remark."
|
||||
),
|
||||
"source_ports": help_text_acl_rule_logic,
|
||||
}
|
||||
|
||||
def clean(self):
|
||||
@ -446,28 +584,38 @@ class ACLExtendedRuleForm(NetBoxModelForm):
|
||||
|
||||
# No need to check for unique_together since there is no usage of GFK
|
||||
|
||||
if cleaned_data.get('action') == 'remark':
|
||||
if cleaned_data.get("action") == "remark":
|
||||
# Check if action set to remark, but no remark set.
|
||||
if not cleaned_data.get('remark'):
|
||||
error_message['remark'] = [error_message_no_remark]
|
||||
if not cleaned_data.get("remark"):
|
||||
error_message["remark"] = [error_message_no_remark]
|
||||
# Check if action set to remark, but source_prefix set.
|
||||
if cleaned_data.get('source_prefix'):
|
||||
error_message['source_prefix'] = [error_message_action_remark_source_prefix_set]
|
||||
if cleaned_data.get("source_prefix"):
|
||||
error_message["source_prefix"] = [
|
||||
error_message_action_remark_source_prefix_set
|
||||
]
|
||||
# Check if action set to remark, but source_ports set.
|
||||
if cleaned_data.get('source_ports'):
|
||||
error_message['source_ports'] = ['Action is set to remark, Source Ports CANNOT be set.']
|
||||
if cleaned_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 cleaned_data.get('destination_prefix'):
|
||||
error_message['destination_prefix'] = ['Action is set to remark, Destination Prefix CANNOT be set.']
|
||||
if cleaned_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 cleaned_data.get('destination_ports'):
|
||||
error_message['destination_ports'] = ['Action is set to remark, Destination Ports CANNOT be set.']
|
||||
if cleaned_data.get("destination_ports"):
|
||||
error_message["destination_ports"] = [
|
||||
"Action is set to remark, Destination Ports CANNOT be set."
|
||||
]
|
||||
# Check if action set to remark, but protocol set.
|
||||
if cleaned_data.get('protocol'):
|
||||
error_message['protocol'] = ['Action is set to remark, Protocol CANNOT be set.']
|
||||
if cleaned_data.get("protocol"):
|
||||
error_message["protocol"] = [
|
||||
"Action is set to remark, Protocol CANNOT be set."
|
||||
]
|
||||
# Check if action not set to remark, but remark set.
|
||||
elif cleaned_data.get('remark'):
|
||||
error_message['remark'] = [error_message_remark_without_action_remark]
|
||||
elif cleaned_data.get("remark"):
|
||||
error_message["remark"] = [error_message_remark_without_action_remark]
|
||||
|
||||
if error_message:
|
||||
raise forms.ValidationError(error_message)
|
||||
|
||||
@ -9,10 +9,10 @@ from netbox.graphql.types import NetBoxObjectType
|
||||
from . import filtersets, models
|
||||
|
||||
__all__ = (
|
||||
'AccessListType',
|
||||
'ACLInterfaceAssignmentType',
|
||||
'ACLExtendedRuleType',
|
||||
'ACLStandardRuleType',
|
||||
"AccessListType",
|
||||
"ACLInterfaceAssignmentType",
|
||||
"ACLExtendedRuleType",
|
||||
"ACLStandardRuleType",
|
||||
)
|
||||
|
||||
#
|
||||
@ -29,8 +29,9 @@ class AccessListType(NetBoxObjectType):
|
||||
"""
|
||||
Associates the filterset, fields, and model for the django model AccessList.
|
||||
"""
|
||||
|
||||
model = models.AccessList
|
||||
fields = '__all__'
|
||||
fields = "__all__"
|
||||
filterset_class = filtersets.AccessListFilterSet
|
||||
|
||||
|
||||
@ -43,8 +44,9 @@ class ACLInterfaceAssignmentType(NetBoxObjectType):
|
||||
"""
|
||||
Associates the filterset, fields, and model for the django model ACLInterfaceAssignment.
|
||||
"""
|
||||
|
||||
model = models.ACLInterfaceAssignment
|
||||
fields = '__all__'
|
||||
fields = "__all__"
|
||||
filterset_class = filtersets.ACLInterfaceAssignmentFilterSet
|
||||
|
||||
|
||||
@ -57,8 +59,9 @@ class ACLExtendedRuleType(NetBoxObjectType):
|
||||
"""
|
||||
Associates the filterset, fields, and model for the django model ACLExtendedRule.
|
||||
"""
|
||||
|
||||
model = models.ACLExtendedRule
|
||||
fields = '__all__'
|
||||
fields = "__all__"
|
||||
filterset_class = filtersets.ACLExtendedRuleFilterSet
|
||||
|
||||
|
||||
@ -71,10 +74,12 @@ class ACLStandardRuleType(NetBoxObjectType):
|
||||
"""
|
||||
Associates the filterset, fields, and model for the django model ACLStandardRule.
|
||||
"""
|
||||
|
||||
model = models.ACLStandardRule
|
||||
fields = '__all__'
|
||||
fields = "__all__"
|
||||
filterset_class = filtersets.ACLStandardRuleFilterSet
|
||||
|
||||
|
||||
#
|
||||
# Queries
|
||||
#
|
||||
@ -94,4 +99,5 @@ class Query(ObjectType):
|
||||
acl_standard_rule = ObjectField(ACLStandardRuleType)
|
||||
acl_standard_rule_list = ObjectListField(ACLStandardRuleType)
|
||||
|
||||
|
||||
schema = Query
|
||||
|
||||
@ -8,9 +8,8 @@ import django.db.models.deletion
|
||||
import taggit.managers
|
||||
from django.db import migrations, models
|
||||
|
||||
__all__ = (
|
||||
'Migration',
|
||||
)
|
||||
__all__ = ("Migration",)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
"""
|
||||
@ -20,100 +19,258 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('extras', '0072_created_datetimefield'),
|
||||
('ipam', '0057_created_datetimefield'),
|
||||
("extras", "0072_created_datetimefield"),
|
||||
("ipam", "0057_created_datetimefield"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AccessList',
|
||||
name="AccessList",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('created', models.DateTimeField(auto_now_add=True, null=True)),
|
||||
('last_updated', models.DateTimeField(auto_now=True, null=True)),
|
||||
('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)),
|
||||
('name', models.CharField(max_length=500)),
|
||||
('assigned_object_id', models.PositiveIntegerField()),
|
||||
('assigned_object_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')),
|
||||
('type', models.CharField(max_length=100)),
|
||||
('default_action', models.CharField(default='deny', max_length=30)),
|
||||
('comments', models.TextField(blank=True)),
|
||||
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
||||
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
||||
(
|
||||
"custom_field_data",
|
||||
models.JSONField(
|
||||
blank=True,
|
||||
default=dict,
|
||||
encoder=django.core.serializers.json.DjangoJSONEncoder,
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=500)),
|
||||
("assigned_object_id", models.PositiveIntegerField()),
|
||||
(
|
||||
"assigned_object_type",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="contenttypes.contenttype",
|
||||
),
|
||||
),
|
||||
("type", models.CharField(max_length=100)),
|
||||
("default_action", models.CharField(default="deny", max_length=30)),
|
||||
("comments", models.TextField(blank=True)),
|
||||
(
|
||||
"tags",
|
||||
taggit.managers.TaggableManager(
|
||||
through="extras.TaggedItem", to="extras.Tag"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'ordering': ('name', 'device'),
|
||||
'unique_together': {('assigned_object_type', 'assigned_object_id', 'name')},
|
||||
'verbose_name': 'Access List',
|
||||
"ordering": ("name", "device"),
|
||||
"unique_together": {
|
||||
("assigned_object_type", "assigned_object_id", "name")
|
||||
},
|
||||
"verbose_name": "Access List",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ACLInterfaceAssignment',
|
||||
name="ACLInterfaceAssignment",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('created', models.DateTimeField(auto_now_add=True, null=True)),
|
||||
('last_updated', models.DateTimeField(auto_now=True, null=True)),
|
||||
('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)),
|
||||
('access_list', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='aclinterfaceassignment', to='netbox_access_lists.accesslist')),
|
||||
('direction', models.CharField(max_length=100)),
|
||||
('assigned_object_id', models.PositiveIntegerField()),
|
||||
('assigned_object_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype')),
|
||||
('comments', models.TextField(blank=True)),
|
||||
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
||||
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
||||
(
|
||||
"custom_field_data",
|
||||
models.JSONField(
|
||||
blank=True,
|
||||
default=dict,
|
||||
encoder=django.core.serializers.json.DjangoJSONEncoder,
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_list",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="aclinterfaceassignment",
|
||||
to="netbox_access_lists.accesslist",
|
||||
),
|
||||
),
|
||||
("direction", models.CharField(max_length=100)),
|
||||
("assigned_object_id", models.PositiveIntegerField()),
|
||||
(
|
||||
"assigned_object_type",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="contenttypes.contenttype",
|
||||
),
|
||||
),
|
||||
("comments", models.TextField(blank=True)),
|
||||
(
|
||||
"tags",
|
||||
taggit.managers.TaggableManager(
|
||||
through="extras.TaggedItem", to="extras.Tag"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'ordering': ('access_list', 'assigned_object_type', 'assigned_object_id', 'direction'),
|
||||
'unique_together': {('assigned_object_type', 'assigned_object_id', 'access_list', 'direction')},
|
||||
'verbose_name': 'ACL Interface Assignment',
|
||||
"ordering": (
|
||||
"access_list",
|
||||
"assigned_object_type",
|
||||
"assigned_object_id",
|
||||
"direction",
|
||||
),
|
||||
"unique_together": {
|
||||
(
|
||||
"assigned_object_type",
|
||||
"assigned_object_id",
|
||||
"access_list",
|
||||
"direction",
|
||||
)
|
||||
},
|
||||
"verbose_name": "ACL Interface Assignment",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ACLStandardRule',
|
||||
name="ACLStandardRule",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('created', models.DateTimeField(auto_now_add=True, null=True)),
|
||||
('last_updated', models.DateTimeField(auto_now=True, null=True)),
|
||||
('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)),
|
||||
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||
('access_list', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='aclstandardrules', to='netbox_access_lists.accesslist')),
|
||||
('index', models.PositiveIntegerField()),
|
||||
('description', models.CharField(blank=True, max_length=500)),
|
||||
('action', models.CharField(max_length=30)),
|
||||
('remark', models.CharField(blank=True, null=True, max_length=500)),
|
||||
('source_prefix', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='ipam.prefix')),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
||||
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
||||
(
|
||||
"custom_field_data",
|
||||
models.JSONField(
|
||||
blank=True,
|
||||
default=dict,
|
||||
encoder=django.core.serializers.json.DjangoJSONEncoder,
|
||||
),
|
||||
),
|
||||
(
|
||||
"tags",
|
||||
taggit.managers.TaggableManager(
|
||||
through="extras.TaggedItem", to="extras.Tag"
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_list",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="aclstandardrules",
|
||||
to="netbox_access_lists.accesslist",
|
||||
),
|
||||
),
|
||||
("index", models.PositiveIntegerField()),
|
||||
("description", models.CharField(blank=True, max_length=500)),
|
||||
("action", models.CharField(max_length=30)),
|
||||
("remark", models.CharField(blank=True, null=True, max_length=500)),
|
||||
(
|
||||
"source_prefix",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="+",
|
||||
to="ipam.prefix",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'ordering': ('access_list', 'index'),
|
||||
'unique_together': {('access_list', 'index')},
|
||||
'verbose_name': 'ACL Standard Rule',
|
||||
"ordering": ("access_list", "index"),
|
||||
"unique_together": {("access_list", "index")},
|
||||
"verbose_name": "ACL Standard Rule",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ACLExtendedRule',
|
||||
name="ACLExtendedRule",
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('created', models.DateTimeField(auto_now_add=True, null=True)),
|
||||
('last_updated', models.DateTimeField(auto_now=True, null=True)),
|
||||
('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)),
|
||||
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||
('access_list', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='aclstandardrules', to='netbox_access_lists.accesslist')),
|
||||
('index', models.PositiveIntegerField()),
|
||||
('description', models.CharField(blank=True, max_length=500)),
|
||||
('action', models.CharField(max_length=30)),
|
||||
('remark', models.CharField(blank=True, null=True, max_length=500)),
|
||||
('source_prefix', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='ipam.prefix')),
|
||||
('source_ports', django.contrib.postgres.fields.ArrayField(base_field=models.PositiveIntegerField(), blank=True, null=True, size=None)),
|
||||
('destination_prefix', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='ipam.prefix')),
|
||||
('destination_ports', django.contrib.postgres.fields.ArrayField(base_field=models.PositiveIntegerField(), blank=True, null=True, size=None)),
|
||||
('protocol', models.CharField(blank=True, max_length=30)),
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
||||
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
||||
(
|
||||
"custom_field_data",
|
||||
models.JSONField(
|
||||
blank=True,
|
||||
default=dict,
|
||||
encoder=django.core.serializers.json.DjangoJSONEncoder,
|
||||
),
|
||||
),
|
||||
(
|
||||
"tags",
|
||||
taggit.managers.TaggableManager(
|
||||
through="extras.TaggedItem", to="extras.Tag"
|
||||
),
|
||||
),
|
||||
(
|
||||
"access_list",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="aclstandardrules",
|
||||
to="netbox_access_lists.accesslist",
|
||||
),
|
||||
),
|
||||
("index", models.PositiveIntegerField()),
|
||||
("description", models.CharField(blank=True, max_length=500)),
|
||||
("action", models.CharField(max_length=30)),
|
||||
("remark", models.CharField(blank=True, null=True, max_length=500)),
|
||||
(
|
||||
"source_prefix",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="+",
|
||||
to="ipam.prefix",
|
||||
),
|
||||
),
|
||||
(
|
||||
"source_ports",
|
||||
django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.PositiveIntegerField(),
|
||||
blank=True,
|
||||
null=True,
|
||||
size=None,
|
||||
),
|
||||
),
|
||||
(
|
||||
"destination_prefix",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="+",
|
||||
to="ipam.prefix",
|
||||
),
|
||||
),
|
||||
(
|
||||
"destination_ports",
|
||||
django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.PositiveIntegerField(),
|
||||
blank=True,
|
||||
null=True,
|
||||
size=None,
|
||||
),
|
||||
),
|
||||
("protocol", models.CharField(blank=True, max_length=30)),
|
||||
],
|
||||
options={
|
||||
'ordering': ('access_list', 'index'),
|
||||
'unique_together': {('access_list', 'index')},
|
||||
'verbose_name': 'ACL Extended Rule',
|
||||
"ordering": ("access_list", "index"),
|
||||
"unique_together": {("access_list", "index")},
|
||||
"verbose_name": "ACL Extended Rule",
|
||||
},
|
||||
),
|
||||
#migrations.AddConstraint(
|
||||
# migrations.AddConstraint(
|
||||
# model_name='accesslist',
|
||||
# constraint=models.UniqueConstraint(fields=('assigned_object_type', 'assigned_object_id'), name='accesslist_assigned_object'),
|
||||
#),
|
||||
# ),
|
||||
]
|
||||
|
||||
@ -11,9 +11,9 @@ from ..choices import *
|
||||
from .access_lists import AccessList
|
||||
|
||||
__all__ = (
|
||||
'ACLRule',
|
||||
'ACLStandardRule',
|
||||
'ACLExtendedRule',
|
||||
"ACLRule",
|
||||
"ACLStandardRule",
|
||||
"ACLExtendedRule",
|
||||
)
|
||||
|
||||
|
||||
@ -22,20 +22,21 @@ class ACLRule(NetBoxModel):
|
||||
Abstract model for ACL Rules.
|
||||
Inherrited by both ACLStandardRule and ACLExtendedRule.
|
||||
"""
|
||||
|
||||
access_list = models.ForeignKey(
|
||||
on_delete=models.CASCADE,
|
||||
to=AccessList,
|
||||
verbose_name='Access List',
|
||||
related_name='rules',
|
||||
verbose_name="Access List",
|
||||
related_name="rules",
|
||||
)
|
||||
index = models.PositiveIntegerField()
|
||||
remark = models.CharField(
|
||||
max_length=500,
|
||||
blank=True
|
||||
blank=True,
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=500,
|
||||
blank=True
|
||||
blank=True,
|
||||
)
|
||||
action = models.CharField(
|
||||
choices=ACLRuleActionChoices,
|
||||
@ -45,13 +46,13 @@ class ACLRule(NetBoxModel):
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='+',
|
||||
to='ipam.Prefix',
|
||||
verbose_name='Source Prefix'
|
||||
related_name="+",
|
||||
to="ipam.Prefix",
|
||||
verbose_name="Source Prefix",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.access_list}: Rule {self.index}'
|
||||
return f"{self.access_list}: Rule {self.index}"
|
||||
|
||||
def get_action_color(self):
|
||||
return ACLRuleActionChoices.colors.get(self.action)
|
||||
@ -63,21 +64,23 @@ class ACLRule(NetBoxModel):
|
||||
- ordering
|
||||
- unique together
|
||||
"""
|
||||
|
||||
abstract = True
|
||||
ordering = ['access_list', 'index']
|
||||
unique_together = ['access_list', 'index']
|
||||
ordering = ["access_list", "index"]
|
||||
unique_together = ["access_list", "index"]
|
||||
|
||||
|
||||
class ACLStandardRule(ACLRule):
|
||||
"""
|
||||
Inherits ACLRule.
|
||||
"""
|
||||
|
||||
access_list = models.ForeignKey(
|
||||
on_delete=models.CASCADE,
|
||||
to=AccessList,
|
||||
verbose_name='Standard Access List',
|
||||
limit_choices_to={'type': 'standard'},
|
||||
related_name='aclstandardrules',
|
||||
verbose_name="Standard Access List",
|
||||
limit_choices_to={"type": "standard"},
|
||||
related_name="aclstandardrules",
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
@ -85,7 +88,7 @@ class ACLStandardRule(ACLRule):
|
||||
The method is a Django convention; although not strictly required,
|
||||
it conveniently returns the absolute URL for any particular object.
|
||||
"""
|
||||
return reverse('plugins:netbox_access_lists:aclstandardrule', args=[self.pk])
|
||||
return reverse("plugins:netbox_access_lists:aclstandardrule", args=[self.pk])
|
||||
|
||||
class Meta(ACLRule.Meta):
|
||||
"""
|
||||
@ -94,40 +97,43 @@ class ACLStandardRule(ACLRule):
|
||||
- verbose name (for displaying in the GUI)
|
||||
- verbose name plural (for displaying in the GUI)
|
||||
"""
|
||||
verbose_name='ACL Standard Rule'
|
||||
verbose_name_plural='ACL Standard Rules'
|
||||
|
||||
verbose_name = "ACL Standard Rule"
|
||||
verbose_name_plural = "ACL Standard Rules"
|
||||
|
||||
|
||||
class ACLExtendedRule(ACLRule):
|
||||
"""
|
||||
Inherits ACLRule.
|
||||
Add ACLExtendedRule specific fields: source_ports, desintation_prefix, destination_ports, and protocol
|
||||
"""
|
||||
|
||||
access_list = models.ForeignKey(
|
||||
on_delete=models.CASCADE,
|
||||
to=AccessList,
|
||||
verbose_name='Extended Access List',
|
||||
limit_choices_to={'type': 'extended'},
|
||||
related_name='aclextendedrules',
|
||||
verbose_name="Extended Access List",
|
||||
limit_choices_to={"type": "extended"},
|
||||
related_name="aclextendedrules",
|
||||
)
|
||||
source_ports = ArrayField(
|
||||
base_field=models.PositiveIntegerField(),
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Soure Ports'
|
||||
verbose_name="Soure Ports",
|
||||
)
|
||||
destination_prefix = models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=models.PROTECT,
|
||||
related_name='+',
|
||||
to='ipam.Prefix',
|
||||
verbose_name='Destination Prefix'
|
||||
related_name="+",
|
||||
to="ipam.Prefix",
|
||||
verbose_name="Destination Prefix",
|
||||
)
|
||||
destination_ports = ArrayField(
|
||||
base_field=models.PositiveIntegerField(),
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='Destination Ports'
|
||||
verbose_name="Destination Ports",
|
||||
)
|
||||
protocol = models.CharField(
|
||||
blank=True,
|
||||
@ -140,7 +146,7 @@ class ACLExtendedRule(ACLRule):
|
||||
The method is a Django convention; although not strictly required,
|
||||
it conveniently returns the absolute URL for any particular object.
|
||||
"""
|
||||
return reverse('plugins:netbox_access_lists:aclextendedrule', args=[self.pk])
|
||||
return reverse("plugins:netbox_access_lists:aclextendedrule", args=[self.pk])
|
||||
|
||||
def get_protocol_color(self):
|
||||
return ACLProtocolChoices.colors.get(self.protocol)
|
||||
@ -152,5 +158,6 @@ class ACLExtendedRule(ACLRule):
|
||||
- verbose name (for displaying in the GUI)
|
||||
- verbose name plural (for displaying in the GUI)
|
||||
"""
|
||||
verbose_name='ACL Extended Rule'
|
||||
verbose_name_plural='ACL Extended Rules'
|
||||
|
||||
verbose_name = "ACL Extended Rule"
|
||||
verbose_name_plural = "ACL Extended Rules"
|
||||
|
||||
@ -3,8 +3,7 @@ Define the django models for this plugin.
|
||||
"""
|
||||
|
||||
from dcim.models import Device, Interface, VirtualChassis
|
||||
from django.contrib.contenttypes.fields import (GenericForeignKey,
|
||||
GenericRelation)
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
@ -13,54 +12,58 @@ from netbox.models import NetBoxModel
|
||||
from virtualization.models import VirtualMachine, VMInterface
|
||||
|
||||
from ..choices import *
|
||||
from ..constants import (ACL_HOST_ASSIGNMENT_MODELS,
|
||||
ACL_INTERFACE_ASSIGNMENT_MODELS)
|
||||
from ..constants import ACL_HOST_ASSIGNMENT_MODELS, ACL_INTERFACE_ASSIGNMENT_MODELS
|
||||
|
||||
__all__ = (
|
||||
'AccessList',
|
||||
'ACLInterfaceAssignment',
|
||||
"AccessList",
|
||||
"ACLInterfaceAssignment",
|
||||
)
|
||||
|
||||
|
||||
alphanumeric_plus = RegexValidator(r'^[0-9a-zA-Z,-,_]*$', 'Only alphanumeric, hyphens, and underscores characters are allowed.')
|
||||
alphanumeric_plus = RegexValidator(
|
||||
r"^[0-9a-zA-Z,-,_]*$",
|
||||
"Only alphanumeric, hyphens, and underscores characters are allowed.",
|
||||
)
|
||||
|
||||
|
||||
class AccessList(NetBoxModel):
|
||||
"""
|
||||
Model defintion for Access Lists.
|
||||
"""
|
||||
|
||||
name = models.CharField(
|
||||
max_length=500,
|
||||
validators=[alphanumeric_plus]
|
||||
validators=[alphanumeric_plus],
|
||||
)
|
||||
assigned_object_type = models.ForeignKey(
|
||||
to=ContentType,
|
||||
limit_choices_to=ACL_HOST_ASSIGNMENT_MODELS,
|
||||
on_delete=models.PROTECT
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
assigned_object_id = models.PositiveBigIntegerField()
|
||||
assigned_object = GenericForeignKey(
|
||||
ct_field='assigned_object_type',
|
||||
fk_field='assigned_object_id'
|
||||
ct_field="assigned_object_type",
|
||||
fk_field="assigned_object_id",
|
||||
)
|
||||
type = models.CharField(
|
||||
max_length=30,
|
||||
choices=ACLTypeChoices
|
||||
choices=ACLTypeChoices,
|
||||
)
|
||||
default_action = models.CharField(
|
||||
default=ACLActionChoices.ACTION_DENY,
|
||||
max_length=30,
|
||||
choices=ACLActionChoices,
|
||||
verbose_name='Default Action'
|
||||
verbose_name="Default Action",
|
||||
)
|
||||
comments = models.TextField(
|
||||
blank=True
|
||||
blank=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = ['assigned_object_type', 'assigned_object_id', 'name']
|
||||
ordering = ['assigned_object_type', 'assigned_object_id', 'name']
|
||||
verbose_name = 'Access List'
|
||||
verbose_name_plural = 'Access Lists'
|
||||
unique_together = ["assigned_object_type", "assigned_object_id", "name"]
|
||||
ordering = ["assigned_object_type", "assigned_object_id", "name"]
|
||||
verbose_name = "Access List"
|
||||
verbose_name_plural = "Access Lists"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -70,7 +73,7 @@ class AccessList(NetBoxModel):
|
||||
The method is a Django convention; although not strictly required,
|
||||
it conveniently returns the absolute URL for any particular object.
|
||||
"""
|
||||
return reverse('plugins:netbox_access_lists:accesslist', args=[self.pk])
|
||||
return reverse("plugins:netbox_access_lists:accesslist", args=[self.pk])
|
||||
|
||||
def get_default_action_color(self):
|
||||
return ACLActionChoices.colors.get(self.default_action)
|
||||
@ -90,38 +93,50 @@ class ACLInterfaceAssignment(NetBoxModel):
|
||||
access_list = models.ForeignKey(
|
||||
on_delete=models.CASCADE,
|
||||
to=AccessList,
|
||||
verbose_name='Access List',
|
||||
verbose_name="Access List",
|
||||
)
|
||||
direction = models.CharField(
|
||||
max_length=30,
|
||||
choices=ACLAssignmentDirectionChoices
|
||||
choices=ACLAssignmentDirectionChoices,
|
||||
)
|
||||
assigned_object_type = models.ForeignKey(
|
||||
to=ContentType,
|
||||
limit_choices_to=ACL_INTERFACE_ASSIGNMENT_MODELS,
|
||||
on_delete=models.PROTECT
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
assigned_object_id = models.PositiveBigIntegerField()
|
||||
assigned_object = GenericForeignKey(
|
||||
ct_field='assigned_object_type',
|
||||
fk_field='assigned_object_id'
|
||||
ct_field="assigned_object_type",
|
||||
fk_field="assigned_object_id",
|
||||
)
|
||||
comments = models.TextField(
|
||||
blank=True
|
||||
blank=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = ['assigned_object_type', 'assigned_object_id', 'access_list', 'direction']
|
||||
ordering = ['assigned_object_type', 'assigned_object_id', 'access_list', 'direction']
|
||||
verbose_name = 'ACL Interface Assignment'
|
||||
verbose_name_plural = 'ACL Interface Assignments'
|
||||
unique_together = [
|
||||
"assigned_object_type",
|
||||
"assigned_object_id",
|
||||
"access_list",
|
||||
"direction",
|
||||
]
|
||||
ordering = [
|
||||
"assigned_object_type",
|
||||
"assigned_object_id",
|
||||
"access_list",
|
||||
"direction",
|
||||
]
|
||||
verbose_name = "ACL Interface Assignment"
|
||||
verbose_name_plural = "ACL Interface Assignments"
|
||||
|
||||
def get_absolute_url(self):
|
||||
"""
|
||||
The method is a Django convention; although not strictly required,
|
||||
it conveniently returns the absolute URL for any particular object.
|
||||
"""
|
||||
return reverse('plugins:netbox_access_lists:aclinterfaceassignment', args=[self.pk])
|
||||
return reverse(
|
||||
"plugins:netbox_access_lists:aclinterfaceassignment", args=[self.pk]
|
||||
)
|
||||
|
||||
def get_direction_color(self):
|
||||
return ACLAssignmentDirectionChoices.colors.get(self.direction)
|
||||
@ -129,35 +144,35 @@ class ACLInterfaceAssignment(NetBoxModel):
|
||||
|
||||
GenericRelation(
|
||||
to=ACLInterfaceAssignment,
|
||||
content_type_field='assigned_object_type',
|
||||
object_id_field='assigned_object_id',
|
||||
related_query_name='interface'
|
||||
).contribute_to_class(Interface, 'accesslistassignments')
|
||||
content_type_field="assigned_object_type",
|
||||
object_id_field="assigned_object_id",
|
||||
related_query_name="interface",
|
||||
).contribute_to_class(Interface, "accesslistassignments")
|
||||
|
||||
GenericRelation(
|
||||
to=ACLInterfaceAssignment,
|
||||
content_type_field='assigned_object_type',
|
||||
object_id_field='assigned_object_id',
|
||||
related_query_name='vminterface'
|
||||
).contribute_to_class(VMInterface, 'accesslistassignments')
|
||||
content_type_field="assigned_object_type",
|
||||
object_id_field="assigned_object_id",
|
||||
related_query_name="vminterface",
|
||||
).contribute_to_class(VMInterface, "accesslistassignments")
|
||||
|
||||
GenericRelation(
|
||||
to=AccessList,
|
||||
content_type_field='assigned_object_type',
|
||||
object_id_field='assigned_object_id',
|
||||
related_query_name='device'
|
||||
).contribute_to_class(Device, 'accesslists')
|
||||
content_type_field="assigned_object_type",
|
||||
object_id_field="assigned_object_id",
|
||||
related_query_name="device",
|
||||
).contribute_to_class(Device, "accesslists")
|
||||
|
||||
GenericRelation(
|
||||
to=AccessList,
|
||||
content_type_field='assigned_object_type',
|
||||
object_id_field='assigned_object_id',
|
||||
related_query_name='virtual_chassis'
|
||||
).contribute_to_class(VirtualChassis, 'accesslists')
|
||||
content_type_field="assigned_object_type",
|
||||
object_id_field="assigned_object_id",
|
||||
related_query_name="virtual_chassis",
|
||||
).contribute_to_class(VirtualChassis, "accesslists")
|
||||
|
||||
GenericRelation(
|
||||
to=AccessList,
|
||||
content_type_field='assigned_object_type',
|
||||
object_id_field='assigned_object_id',
|
||||
related_query_name='virtual_machine'
|
||||
).contribute_to_class(VirtualMachine, 'accesslists')
|
||||
content_type_field="assigned_object_type",
|
||||
object_id_field="assigned_object_id",
|
||||
related_query_name="virtual_machine",
|
||||
).contribute_to_class(VirtualMachine, "accesslists")
|
||||
|
||||
@ -11,38 +11,38 @@ from utilities.choices import ButtonColorChoices
|
||||
|
||||
accesslist_buttons = [
|
||||
PluginMenuButton(
|
||||
link='plugins:netbox_access_lists:accesslist_add',
|
||||
title='Add',
|
||||
icon_class='mdi mdi-plus-thick',
|
||||
color=ButtonColorChoices.GREEN
|
||||
)
|
||||
link="plugins:netbox_access_lists:accesslist_add",
|
||||
title="Add",
|
||||
icon_class="mdi mdi-plus-thick",
|
||||
color=ButtonColorChoices.GREEN,
|
||||
),
|
||||
]
|
||||
|
||||
aclstandardrule_butons = [
|
||||
PluginMenuButton(
|
||||
link='plugins:netbox_access_lists:aclstandardrule_add',
|
||||
title='Add',
|
||||
icon_class='mdi mdi-plus-thick',
|
||||
color=ButtonColorChoices.GREEN
|
||||
)
|
||||
link="plugins:netbox_access_lists:aclstandardrule_add",
|
||||
title="Add",
|
||||
icon_class="mdi mdi-plus-thick",
|
||||
color=ButtonColorChoices.GREEN,
|
||||
),
|
||||
]
|
||||
|
||||
aclextendedrule_butons = [
|
||||
PluginMenuButton(
|
||||
link='plugins:netbox_access_lists:aclextendedrule_add',
|
||||
title='Add',
|
||||
icon_class='mdi mdi-plus-thick',
|
||||
color=ButtonColorChoices.GREEN
|
||||
)
|
||||
link="plugins:netbox_access_lists:aclextendedrule_add",
|
||||
title="Add",
|
||||
icon_class="mdi mdi-plus-thick",
|
||||
color=ButtonColorChoices.GREEN,
|
||||
),
|
||||
]
|
||||
|
||||
accesslistassignment_buttons = [
|
||||
PluginMenuButton(
|
||||
link='plugins:netbox_access_lists:aclinterfaceassignment_add',
|
||||
title='Add',
|
||||
icon_class='mdi mdi-plus-thick',
|
||||
color=ButtonColorChoices.GREEN
|
||||
)
|
||||
link="plugins:netbox_access_lists:aclinterfaceassignment_add",
|
||||
title="Add",
|
||||
icon_class="mdi mdi-plus-thick",
|
||||
color=ButtonColorChoices.GREEN,
|
||||
),
|
||||
]
|
||||
|
||||
#
|
||||
@ -51,25 +51,25 @@ accesslistassignment_buttons = [
|
||||
|
||||
menu_items = (
|
||||
PluginMenuItem(
|
||||
link='plugins:netbox_access_lists:accesslist_list',
|
||||
link_text='Access Lists',
|
||||
buttons=accesslist_buttons
|
||||
link="plugins:netbox_access_lists:accesslist_list",
|
||||
link_text="Access Lists",
|
||||
buttons=accesslist_buttons,
|
||||
),
|
||||
# Comment out Standard Access List rule to force creation in the ACL view
|
||||
PluginMenuItem(
|
||||
link='plugins:netbox_access_lists:aclstandardrule_list',
|
||||
link_text='ACL Standard Rules',
|
||||
buttons=aclstandardrule_butons
|
||||
link="plugins:netbox_access_lists:aclstandardrule_list",
|
||||
link_text="ACL Standard Rules",
|
||||
buttons=aclstandardrule_butons,
|
||||
),
|
||||
# Comment out Extended Access List rule to force creation in the ACL view
|
||||
PluginMenuItem(
|
||||
link='plugins:netbox_access_lists:aclextendedrule_list',
|
||||
link_text='ACL Extended Rules',
|
||||
buttons=aclextendedrule_butons
|
||||
link="plugins:netbox_access_lists:aclextendedrule_list",
|
||||
link_text="ACL Extended Rules",
|
||||
buttons=aclextendedrule_butons,
|
||||
),
|
||||
PluginMenuItem(
|
||||
link='plugins:netbox_access_lists:aclinterfaceassignment_list',
|
||||
link_text='ACL Interface Assignments',
|
||||
buttons=accesslistassignment_buttons
|
||||
link="plugins:netbox_access_lists:aclinterfaceassignment_list",
|
||||
link_text="ACL Interface Assignments",
|
||||
buttons=accesslistassignment_buttons,
|
||||
),
|
||||
)
|
||||
|
||||
@ -3,17 +3,15 @@ Define the object lists / table view for each of the plugin models.
|
||||
"""
|
||||
|
||||
import django_tables2 as tables
|
||||
from netbox.tables import (ChoiceFieldColumn, NetBoxTable, TemplateColumn,
|
||||
columns)
|
||||
from netbox.tables import ChoiceFieldColumn, NetBoxTable, TemplateColumn, columns
|
||||
|
||||
from .models import (AccessList, ACLExtendedRule, ACLInterfaceAssignment,
|
||||
ACLStandardRule)
|
||||
from .models import AccessList, ACLExtendedRule, ACLInterfaceAssignment, ACLStandardRule
|
||||
|
||||
__all__ = (
|
||||
'AccessListTable',
|
||||
'ACLInterfaceAssignmentTable',
|
||||
'ACLStandardRuleTable',
|
||||
'ACLExtendedRuleTable',
|
||||
"AccessListTable",
|
||||
"ACLInterfaceAssignmentTable",
|
||||
"ACLStandardRuleTable",
|
||||
"ACLExtendedRuleTable",
|
||||
)
|
||||
|
||||
|
||||
@ -25,93 +23,144 @@ COL_HOST_ASSIGNMENT = """
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
|
||||
class AccessListTable(NetBoxTable):
|
||||
"""
|
||||
Defines the table view for the AccessList model.
|
||||
"""
|
||||
|
||||
pk = columns.ToggleColumn()
|
||||
id = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
assigned_object = tables.Column(
|
||||
linkify=True,
|
||||
orderable=False,
|
||||
verbose_name='Assigned Host'
|
||||
verbose_name="Assigned Host",
|
||||
)
|
||||
name = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
device = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
type = ChoiceFieldColumn()
|
||||
default_action = ChoiceFieldColumn()
|
||||
rule_count = tables.Column(
|
||||
verbose_name='Rule Count'
|
||||
verbose_name="Rule Count",
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='plugins:netbox_access_lists:accesslist_list'
|
||||
url_name="plugins:netbox_access_lists:accesslist_list",
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = AccessList
|
||||
fields = ('pk', 'id', 'name', 'assigned_object', 'type', 'rule_count', 'default_action', 'comments', 'actions', 'tags')
|
||||
default_columns = ('name', 'assigned_object', 'type', 'rule_count', 'default_action', 'tags')
|
||||
fields = (
|
||||
"pk",
|
||||
"id",
|
||||
"name",
|
||||
"assigned_object",
|
||||
"type",
|
||||
"rule_count",
|
||||
"default_action",
|
||||
"comments",
|
||||
"actions",
|
||||
"tags",
|
||||
)
|
||||
default_columns = (
|
||||
"name",
|
||||
"assigned_object",
|
||||
"type",
|
||||
"rule_count",
|
||||
"default_action",
|
||||
"tags",
|
||||
)
|
||||
|
||||
|
||||
class ACLInterfaceAssignmentTable(NetBoxTable):
|
||||
"""
|
||||
Defines the table view for the AccessList model.
|
||||
"""
|
||||
|
||||
pk = columns.ToggleColumn()
|
||||
id = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
access_list = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
direction = ChoiceFieldColumn()
|
||||
host = tables.TemplateColumn(
|
||||
template_code=COL_HOST_ASSIGNMENT
|
||||
|
||||
template_code=COL_HOST_ASSIGNMENT,
|
||||
)
|
||||
assigned_object = tables.Column(
|
||||
linkify=True,
|
||||
orderable=False,
|
||||
verbose_name='Assigned Interface'
|
||||
verbose_name="Assigned Interface",
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='plugins:netbox_access_lists:aclinterfaceassignment_list'
|
||||
url_name="plugins:netbox_access_lists:aclinterfaceassignment_list",
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = ACLInterfaceAssignment
|
||||
fields = ('pk', 'id', 'access_list', 'direction', 'host', 'assigned_object', 'tags')
|
||||
default_columns = ('id', 'access_list', 'direction', 'host', 'assigned_object', 'tags')
|
||||
fields = (
|
||||
"pk",
|
||||
"id",
|
||||
"access_list",
|
||||
"direction",
|
||||
"host",
|
||||
"assigned_object",
|
||||
"tags",
|
||||
)
|
||||
default_columns = (
|
||||
"id",
|
||||
"access_list",
|
||||
"direction",
|
||||
"host",
|
||||
"assigned_object",
|
||||
"tags",
|
||||
)
|
||||
|
||||
|
||||
class ACLStandardRuleTable(NetBoxTable):
|
||||
"""
|
||||
Defines the table view for the ACLStandardRule model.
|
||||
"""
|
||||
|
||||
access_list = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
index = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
action = ChoiceFieldColumn()
|
||||
tags = columns.TagColumn(
|
||||
url_name='plugins:netbox_access_lists:aclstandardrule_list'
|
||||
url_name="plugins:netbox_access_lists:aclstandardrule_list",
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = ACLStandardRule
|
||||
fields = (
|
||||
'pk', 'id', 'access_list', 'index', 'action', 'actions', 'remark', 'tags', 'description', 'source_prefix',
|
||||
"pk",
|
||||
"id",
|
||||
"access_list",
|
||||
"index",
|
||||
"action",
|
||||
"actions",
|
||||
"remark",
|
||||
"tags",
|
||||
"description",
|
||||
"source_prefix",
|
||||
)
|
||||
default_columns = (
|
||||
'access_list', 'index', 'action', 'actions', 'remark', 'source_prefix', 'tags'
|
||||
"access_list",
|
||||
"index",
|
||||
"action",
|
||||
"actions",
|
||||
"remark",
|
||||
"source_prefix",
|
||||
"tags",
|
||||
)
|
||||
|
||||
|
||||
@ -119,25 +168,47 @@ class ACLExtendedRuleTable(NetBoxTable):
|
||||
"""
|
||||
Defines the table view for the ACLExtendedRule model.
|
||||
"""
|
||||
|
||||
access_list = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
index = tables.Column(
|
||||
linkify=True
|
||||
linkify=True,
|
||||
)
|
||||
action = ChoiceFieldColumn()
|
||||
tags = columns.TagColumn(
|
||||
url_name='plugins:netbox_access_lists:aclextendedrule_list'
|
||||
url_name="plugins:netbox_access_lists:aclextendedrule_list",
|
||||
)
|
||||
protocol = ChoiceFieldColumn()
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = ACLExtendedRule
|
||||
fields = (
|
||||
'pk', 'id', 'access_list', 'index', 'action', 'actions', 'remark', 'tags', 'description',
|
||||
'source_prefix', 'source_ports', 'destination_prefix', 'destination_ports', 'protocol'
|
||||
"pk",
|
||||
"id",
|
||||
"access_list",
|
||||
"index",
|
||||
"action",
|
||||
"actions",
|
||||
"remark",
|
||||
"tags",
|
||||
"description",
|
||||
"source_prefix",
|
||||
"source_ports",
|
||||
"destination_prefix",
|
||||
"destination_ports",
|
||||
"protocol",
|
||||
)
|
||||
default_columns = (
|
||||
'access_list', 'index', 'action', 'actions', 'remark', 'tags',
|
||||
'source_prefix', 'source_ports', 'destination_prefix', 'destination_ports', 'protocol'
|
||||
"access_list",
|
||||
"index",
|
||||
"action",
|
||||
"actions",
|
||||
"remark",
|
||||
"tags",
|
||||
"source_prefix",
|
||||
"source_ports",
|
||||
"destination_prefix",
|
||||
"destination_ports",
|
||||
"protocol",
|
||||
)
|
||||
|
||||
@ -1,70 +1,87 @@
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from extras.plugins import PluginTemplateExtension
|
||||
|
||||
from .models import AccessList, ACLInterfaceAssignment
|
||||
|
||||
__all__ = (
|
||||
'AccessLists',
|
||||
"AccessLists",
|
||||
"ACLInterfaceAssignments",
|
||||
'DeviceAccessLists',
|
||||
'VirtualChassisAccessLists',
|
||||
'VMAccessLists',
|
||||
'DeviceACLInterfaceAssignments',
|
||||
'VMAACLInterfaceAssignments',
|
||||
"DeviceAccessLists",
|
||||
"VirtualChassisAccessLists",
|
||||
"VMAccessLists",
|
||||
"DeviceACLInterfaceAssignments",
|
||||
"VMAACLInterfaceAssignments",
|
||||
)
|
||||
|
||||
|
||||
class ACLInterfaceAssignments(PluginTemplateExtension):
|
||||
|
||||
def right_page(self):
|
||||
obj = self.context['object']
|
||||
obj = self.context["object"]
|
||||
|
||||
acl_interface_assignments = None
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
if ctype.model in ['interface', 'vminterface']:
|
||||
acl_interface_assignments = ACLInterfaceAssignment.objects.filter(assigned_object_id=obj.pk, assigned_object_type=ctype)
|
||||
if ctype.model in ["interface", "vminterface"]:
|
||||
acl_interface_assignments = ACLInterfaceAssignment.objects.filter(
|
||||
assigned_object_id=obj.pk, assigned_object_type=ctype
|
||||
)
|
||||
|
||||
return self.render('inc/assigned_interface/access_lists.html', extra_context={
|
||||
'acl_interface_assignments': acl_interface_assignments,
|
||||
'type': ctype.model if ctype.model == 'device' else ctype.name.replace(' ', '_'),
|
||||
})
|
||||
return self.render(
|
||||
"inc/assigned_interface/access_lists.html",
|
||||
extra_context={
|
||||
"acl_interface_assignments": acl_interface_assignments,
|
||||
"type": ctype.model
|
||||
if ctype.model == "device"
|
||||
else ctype.name.replace(" ", "_"),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class AccessLists(PluginTemplateExtension):
|
||||
|
||||
def right_page(self):
|
||||
obj = self.context['object']
|
||||
obj = self.context["object"]
|
||||
|
||||
access_lists = None
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
if ctype.model in ['device', 'virtualchassis', 'virtualmachine']:
|
||||
access_lists = AccessList.objects.filter(assigned_object_id=obj.pk, assigned_object_type=ctype)
|
||||
if ctype.model in ["device", "virtualchassis", "virtualmachine"]:
|
||||
access_lists = AccessList.objects.filter(
|
||||
assigned_object_id=obj.pk, assigned_object_type=ctype
|
||||
)
|
||||
|
||||
return self.render('inc/assigned_host/access_lists.html', extra_context={
|
||||
'access_lists': access_lists,
|
||||
'type': ctype.model if ctype.model == 'device' else ctype.name.replace(' ', '_'),
|
||||
})
|
||||
return self.render(
|
||||
"inc/assigned_host/access_lists.html",
|
||||
extra_context={
|
||||
"access_lists": access_lists,
|
||||
"type": ctype.model
|
||||
if ctype.model == "device"
|
||||
else ctype.name.replace(" ", "_"),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class DeviceAccessLists(AccessLists):
|
||||
model = 'dcim.device'
|
||||
model = "dcim.device"
|
||||
|
||||
|
||||
class VirtualChassisAccessLists(AccessLists):
|
||||
model = 'dcim.virtualchassis'
|
||||
model = "dcim.virtualchassis"
|
||||
|
||||
|
||||
class VMAccessLists(AccessLists):
|
||||
model = 'virtualization.virtualmachine'
|
||||
model = "virtualization.virtualmachine"
|
||||
|
||||
|
||||
class DeviceACLInterfaceAssignments(ACLInterfaceAssignments):
|
||||
model = 'dcim.interface'
|
||||
model = "dcim.interface"
|
||||
|
||||
|
||||
class VMAACLInterfaceAssignments(ACLInterfaceAssignments):
|
||||
model = 'virtualization.vminterface'
|
||||
model = "virtualization.vminterface"
|
||||
|
||||
|
||||
template_extensions = [DeviceAccessLists, VirtualChassisAccessLists, VMAccessLists, DeviceACLInterfaceAssignments, VMAACLInterfaceAssignments]
|
||||
template_extensions = [
|
||||
DeviceAccessLists,
|
||||
VirtualChassisAccessLists,
|
||||
VMAccessLists,
|
||||
DeviceACLInterfaceAssignments,
|
||||
VMAACLInterfaceAssignments,
|
||||
]
|
||||
|
||||
@ -8,51 +8,152 @@ from netbox.views.generic import ObjectChangeLogView
|
||||
from . import models, views
|
||||
|
||||
urlpatterns = (
|
||||
|
||||
# Access Lists
|
||||
path('access-lists/', views.AccessListListView.as_view(), name='accesslist_list'),
|
||||
path('access-lists/add/', views.AccessListEditView.as_view(), name='accesslist_add'),
|
||||
#path('access-lists/edit/', views.AccessListBulkEditView.as_view(), name='accesslist_bulk_edit'),
|
||||
path('access-lists/delete/', views.AccessListBulkDeleteView.as_view(), name='accesslist_bulk_delete'),
|
||||
path('access-lists/<int:pk>/', views.AccessListView.as_view(), name='accesslist'),
|
||||
path('access-lists/<int:pk>/edit/', views.AccessListEditView.as_view(), name='accesslist_edit'),
|
||||
path('access-lists/<int:pk>/delete/', views.AccessListDeleteView.as_view(), name='accesslist_delete'),
|
||||
path('access-lists/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='accesslist_changelog', kwargs={
|
||||
'model': models.AccessList
|
||||
}),
|
||||
|
||||
path("access-lists/", views.AccessListListView.as_view(), name="accesslist_list"),
|
||||
path(
|
||||
"access-lists/add/", views.AccessListEditView.as_view(), name="accesslist_add"
|
||||
),
|
||||
# path('access-lists/edit/', views.AccessListBulkEditView.as_view(), name='accesslist_bulk_edit'),
|
||||
path(
|
||||
"access-lists/delete/",
|
||||
views.AccessListBulkDeleteView.as_view(),
|
||||
name="accesslist_bulk_delete",
|
||||
),
|
||||
path("access-lists/<int:pk>/", views.AccessListView.as_view(), name="accesslist"),
|
||||
path(
|
||||
"access-lists/<int:pk>/edit/",
|
||||
views.AccessListEditView.as_view(),
|
||||
name="accesslist_edit",
|
||||
),
|
||||
path(
|
||||
"access-lists/<int:pk>/delete/",
|
||||
views.AccessListDeleteView.as_view(),
|
||||
name="accesslist_delete",
|
||||
),
|
||||
path(
|
||||
"access-lists/<int:pk>/changelog/",
|
||||
ObjectChangeLogView.as_view(),
|
||||
name="accesslist_changelog",
|
||||
kwargs={
|
||||
"model": models.AccessList,
|
||||
},
|
||||
),
|
||||
# Access List Interface Assignments
|
||||
path('interface-assignments/', views.ACLInterfaceAssignmentListView.as_view(), name='aclinterfaceassignment_list'),
|
||||
path('interface-assignments/add/', views.ACLInterfaceAssignmentEditView.as_view(), name='aclinterfaceassignment_add'),
|
||||
#path('interface-assignments/edit/', views.ACLInterfaceAssignmentBulkEditView.as_view(), name='aclinterfaceassignment_bulk_edit'),
|
||||
path('interface-assignments/delete/', views.ACLInterfaceAssignmentBulkDeleteView.as_view(), name='aclinterfaceassignment_bulk_delete'),
|
||||
path('interface-assignments/<int:pk>/', views.ACLInterfaceAssignmentView.as_view(), name='aclinterfaceassignment'),
|
||||
path('interface-assignments/<int:pk>/edit/', views.ACLInterfaceAssignmentEditView.as_view(), name='aclinterfaceassignment_edit'),
|
||||
path('interface-assignments/<int:pk>/delete/', views.ACLInterfaceAssignmentDeleteView.as_view(), name='aclinterfaceassignment_delete'),
|
||||
path('interface-assignments/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='aclinterfaceassignment_changelog', kwargs={
|
||||
'model': models.ACLInterfaceAssignment
|
||||
}),
|
||||
|
||||
path(
|
||||
"interface-assignments/",
|
||||
views.ACLInterfaceAssignmentListView.as_view(),
|
||||
name="aclinterfaceassignment_list",
|
||||
),
|
||||
path(
|
||||
"interface-assignments/add/",
|
||||
views.ACLInterfaceAssignmentEditView.as_view(),
|
||||
name="aclinterfaceassignment_add",
|
||||
),
|
||||
# path('interface-assignments/edit/', views.ACLInterfaceAssignmentBulkEditView.as_view(), name='aclinterfaceassignment_bulk_edit'),
|
||||
path(
|
||||
"interface-assignments/delete/",
|
||||
views.ACLInterfaceAssignmentBulkDeleteView.as_view(),
|
||||
name="aclinterfaceassignment_bulk_delete",
|
||||
),
|
||||
path(
|
||||
"interface-assignments/<int:pk>/",
|
||||
views.ACLInterfaceAssignmentView.as_view(),
|
||||
name="aclinterfaceassignment",
|
||||
),
|
||||
path(
|
||||
"interface-assignments/<int:pk>/edit/",
|
||||
views.ACLInterfaceAssignmentEditView.as_view(),
|
||||
name="aclinterfaceassignment_edit",
|
||||
),
|
||||
path(
|
||||
"interface-assignments/<int:pk>/delete/",
|
||||
views.ACLInterfaceAssignmentDeleteView.as_view(),
|
||||
name="aclinterfaceassignment_delete",
|
||||
),
|
||||
path(
|
||||
"interface-assignments/<int:pk>/changelog/",
|
||||
ObjectChangeLogView.as_view(),
|
||||
name="aclinterfaceassignment_changelog",
|
||||
kwargs={
|
||||
"model": models.ACLInterfaceAssignment,
|
||||
},
|
||||
),
|
||||
# Standard Access List Rules
|
||||
path('standard-rules/', views.ACLStandardRuleListView.as_view(), name='aclstandardrule_list'),
|
||||
path('standard-rules/add/', views.ACLStandardRuleEditView.as_view(), name='aclstandardrule_add'),
|
||||
path('standard-rules/delete/', views.ACLStandardRuleBulkDeleteView.as_view(), name='aclstandardrule_bulk_delete'),
|
||||
path('standard-rules/<int:pk>/', views.ACLStandardRuleView.as_view(), name='aclstandardrule'),
|
||||
path('standard-rules/<int:pk>/edit/', views.ACLStandardRuleEditView.as_view(), name='aclstandardrule_edit'),
|
||||
path('standard-rules/<int:pk>/delete/', views.ACLStandardRuleDeleteView.as_view(), name='aclstandardrule_delete'),
|
||||
path('standard-rules/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='aclstandardrule_changelog', kwargs={
|
||||
'model': models.ACLStandardRule
|
||||
}),
|
||||
|
||||
path(
|
||||
"standard-rules/",
|
||||
views.ACLStandardRuleListView.as_view(),
|
||||
name="aclstandardrule_list",
|
||||
),
|
||||
path(
|
||||
"standard-rules/add/",
|
||||
views.ACLStandardRuleEditView.as_view(),
|
||||
name="aclstandardrule_add",
|
||||
),
|
||||
path(
|
||||
"standard-rules/delete/",
|
||||
views.ACLStandardRuleBulkDeleteView.as_view(),
|
||||
name="aclstandardrule_bulk_delete",
|
||||
),
|
||||
path(
|
||||
"standard-rules/<int:pk>/",
|
||||
views.ACLStandardRuleView.as_view(),
|
||||
name="aclstandardrule",
|
||||
),
|
||||
path(
|
||||
"standard-rules/<int:pk>/edit/",
|
||||
views.ACLStandardRuleEditView.as_view(),
|
||||
name="aclstandardrule_edit",
|
||||
),
|
||||
path(
|
||||
"standard-rules/<int:pk>/delete/",
|
||||
views.ACLStandardRuleDeleteView.as_view(),
|
||||
name="aclstandardrule_delete",
|
||||
),
|
||||
path(
|
||||
"standard-rules/<int:pk>/changelog/",
|
||||
ObjectChangeLogView.as_view(),
|
||||
name="aclstandardrule_changelog",
|
||||
kwargs={
|
||||
"model": models.ACLStandardRule,
|
||||
},
|
||||
),
|
||||
# Extended Access List Rules
|
||||
path('extended-rules/', views.ACLExtendedRuleListView.as_view(), name='aclextendedrule_list'),
|
||||
path('extended-rules/add/', views.ACLExtendedRuleEditView.as_view(), name='aclextendedrule_add'),
|
||||
path('extended-rules/delete/', views.ACLExtendedRuleBulkDeleteView.as_view(), name='aclextendedrule_bulk_delete'),
|
||||
path('extended-rules/<int:pk>/', views.ACLExtendedRuleView.as_view(), name='aclextendedrule'),
|
||||
path('extended-rules/<int:pk>/edit/', views.ACLExtendedRuleEditView.as_view(), name='aclextendedrule_edit'),
|
||||
path('extended-rules/<int:pk>/delete/', views.ACLExtendedRuleDeleteView.as_view(), name='aclextendedrule_delete'),
|
||||
path('extended-rules/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='aclextendedrule_changelog', kwargs={
|
||||
'model': models.ACLExtendedRule
|
||||
}),
|
||||
|
||||
path(
|
||||
"extended-rules/",
|
||||
views.ACLExtendedRuleListView.as_view(),
|
||||
name="aclextendedrule_list",
|
||||
),
|
||||
path(
|
||||
"extended-rules/add/",
|
||||
views.ACLExtendedRuleEditView.as_view(),
|
||||
name="aclextendedrule_add",
|
||||
),
|
||||
path(
|
||||
"extended-rules/delete/",
|
||||
views.ACLExtendedRuleBulkDeleteView.as_view(),
|
||||
name="aclextendedrule_bulk_delete",
|
||||
),
|
||||
path(
|
||||
"extended-rules/<int:pk>/",
|
||||
views.ACLExtendedRuleView.as_view(),
|
||||
name="aclextendedrule",
|
||||
),
|
||||
path(
|
||||
"extended-rules/<int:pk>/edit/",
|
||||
views.ACLExtendedRuleEditView.as_view(),
|
||||
name="aclextendedrule_edit",
|
||||
),
|
||||
path(
|
||||
"extended-rules/<int:pk>/delete/",
|
||||
views.ACLExtendedRuleDeleteView.as_view(),
|
||||
name="aclextendedrule_delete",
|
||||
),
|
||||
path(
|
||||
"extended-rules/<int:pk>/changelog/",
|
||||
ObjectChangeLogView.as_view(),
|
||||
name="aclextendedrule_changelog",
|
||||
kwargs={
|
||||
"model": models.ACLExtendedRule,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
@ -9,26 +9,26 @@ from netbox.views import generic
|
||||
from . import filtersets, forms, models, tables
|
||||
|
||||
__all__ = (
|
||||
'AccessListView',
|
||||
'AccessListListView',
|
||||
'AccessListEditView',
|
||||
'AccessListDeleteView',
|
||||
'AccessListBulkDeleteView',
|
||||
'ACLInterfaceAssignmentView',
|
||||
'ACLInterfaceAssignmentListView',
|
||||
'ACLInterfaceAssignmentEditView',
|
||||
'ACLInterfaceAssignmentDeleteView',
|
||||
'ACLInterfaceAssignmentBulkDeleteView',
|
||||
'ACLStandardRuleView',
|
||||
'ACLStandardRuleListView',
|
||||
'ACLStandardRuleEditView',
|
||||
'ACLStandardRuleDeleteView',
|
||||
'ACLStandardRuleBulkDeleteView',
|
||||
'ACLExtendedRuleView',
|
||||
'ACLExtendedRuleListView',
|
||||
'ACLExtendedRuleEditView',
|
||||
'ACLExtendedRuleDeleteView',
|
||||
'ACLExtendedRuleBulkDeleteView',
|
||||
"AccessListView",
|
||||
"AccessListListView",
|
||||
"AccessListEditView",
|
||||
"AccessListDeleteView",
|
||||
"AccessListBulkDeleteView",
|
||||
"ACLInterfaceAssignmentView",
|
||||
"ACLInterfaceAssignmentListView",
|
||||
"ACLInterfaceAssignmentEditView",
|
||||
"ACLInterfaceAssignmentDeleteView",
|
||||
"ACLInterfaceAssignmentBulkDeleteView",
|
||||
"ACLStandardRuleView",
|
||||
"ACLStandardRuleListView",
|
||||
"ACLStandardRuleEditView",
|
||||
"ACLStandardRuleDeleteView",
|
||||
"ACLStandardRuleBulkDeleteView",
|
||||
"ACLExtendedRuleView",
|
||||
"ACLExtendedRuleListView",
|
||||
"ACLExtendedRuleEditView",
|
||||
"ACLExtendedRuleDeleteView",
|
||||
"ACLExtendedRuleBulkDeleteView",
|
||||
)
|
||||
|
||||
|
||||
@ -36,24 +36,26 @@ __all__ = (
|
||||
# AccessList views
|
||||
#
|
||||
|
||||
|
||||
class AccessListView(generic.ObjectView):
|
||||
"""
|
||||
Defines the view for the AccessLists django model.
|
||||
"""
|
||||
|
||||
queryset = models.AccessList.objects.all()
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
"""
|
||||
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':
|
||||
if instance.type == "extended":
|
||||
table = tables.ACLExtendedRuleTable(instance.aclextendedrules.all())
|
||||
elif instance.type == 'standard':
|
||||
elif instance.type == "standard":
|
||||
table = tables.ACLStandardRuleTable(instance.aclstandardrules.all())
|
||||
table.configure(request)
|
||||
|
||||
return {
|
||||
'rules_table': table
|
||||
"rules_table": table,
|
||||
}
|
||||
|
||||
|
||||
@ -61,8 +63,9 @@ class AccessListListView(generic.ObjectListView):
|
||||
"""
|
||||
Defines the list view for the AccessLists django model.
|
||||
"""
|
||||
|
||||
queryset = models.AccessList.objects.annotate(
|
||||
rule_count=Count('aclextendedrules') + Count('aclstandardrules')
|
||||
rule_count=Count("aclextendedrules") + Count("aclstandardrules"),
|
||||
)
|
||||
table = tables.AccessListTable
|
||||
filterset = filtersets.AccessListFilterSet
|
||||
@ -73,15 +76,17 @@ class AccessListEditView(generic.ObjectEditView):
|
||||
"""
|
||||
Defines the edit view for the AccessLists django model.
|
||||
"""
|
||||
|
||||
queryset = models.AccessList.objects.all()
|
||||
form = forms.AccessListForm
|
||||
template_name = 'netbox_access_lists/accesslist_edit.html'
|
||||
template_name = "netbox_access_lists/accesslist_edit.html"
|
||||
|
||||
|
||||
class AccessListDeleteView(generic.ObjectDeleteView):
|
||||
"""
|
||||
Defines the delete view for the AccessLists django model.
|
||||
"""
|
||||
|
||||
queryset = models.AccessList.objects.all()
|
||||
|
||||
|
||||
@ -90,14 +95,17 @@ class AccessListBulkDeleteView(generic.BulkDeleteView):
|
||||
filterset = filtersets.AccessListFilterSet
|
||||
table = tables.AccessListTable
|
||||
|
||||
|
||||
#
|
||||
# ACLInterfaceAssignment views
|
||||
#
|
||||
|
||||
|
||||
class ACLInterfaceAssignmentView(generic.ObjectView):
|
||||
"""
|
||||
Defines the view for the ACLInterfaceAssignments django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLInterfaceAssignment.objects.all()
|
||||
|
||||
|
||||
@ -105,6 +113,7 @@ class ACLInterfaceAssignmentListView(generic.ObjectListView):
|
||||
"""
|
||||
Defines the list view for the ACLInterfaceAssignments django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLInterfaceAssignment.objects.all()
|
||||
table = tables.ACLInterfaceAssignmentTable
|
||||
filterset = filtersets.ACLInterfaceAssignmentFilterSet
|
||||
@ -115,15 +124,17 @@ class ACLInterfaceAssignmentEditView(generic.ObjectEditView):
|
||||
"""
|
||||
Defines the edit view for the ACLInterfaceAssignments django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLInterfaceAssignment.objects.all()
|
||||
form = forms.ACLInterfaceAssignmentForm
|
||||
template_name = 'netbox_access_lists/aclinterfaceassignment_edit.html'
|
||||
template_name = "netbox_access_lists/aclinterfaceassignment_edit.html"
|
||||
|
||||
|
||||
class ACLInterfaceAssignmentDeleteView(generic.ObjectDeleteView):
|
||||
"""
|
||||
Defines the delete view for the ACLInterfaceAssignments django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLInterfaceAssignment.objects.all()
|
||||
|
||||
|
||||
@ -142,6 +153,7 @@ class ACLStandardRuleView(generic.ObjectView):
|
||||
"""
|
||||
Defines the view for the ACLStandardRule django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLStandardRule.objects.all()
|
||||
|
||||
|
||||
@ -149,6 +161,7 @@ class ACLStandardRuleListView(generic.ObjectListView):
|
||||
"""
|
||||
Defines the list view for the ACLStandardRule django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLStandardRule.objects.all()
|
||||
table = tables.ACLStandardRuleTable
|
||||
filterset = filtersets.ACLStandardRuleFilterSet
|
||||
@ -159,6 +172,7 @@ class ACLStandardRuleEditView(generic.ObjectEditView):
|
||||
"""
|
||||
Defines the edit view for the ACLStandardRule django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLStandardRule.objects.all()
|
||||
form = forms.ACLStandardRuleForm
|
||||
|
||||
@ -167,6 +181,7 @@ class ACLStandardRuleDeleteView(generic.ObjectDeleteView):
|
||||
"""
|
||||
Defines the delete view for the ACLStandardRules django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLStandardRule.objects.all()
|
||||
|
||||
|
||||
@ -175,6 +190,7 @@ class ACLStandardRuleBulkDeleteView(generic.BulkDeleteView):
|
||||
filterset = filtersets.ACLStandardRuleFilterSet
|
||||
table = tables.ACLStandardRuleTable
|
||||
|
||||
|
||||
#
|
||||
# ACLExtendedRule views
|
||||
#
|
||||
@ -184,6 +200,7 @@ class ACLExtendedRuleView(generic.ObjectView):
|
||||
"""
|
||||
Defines the view for the ACLExtendedRule django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLExtendedRule.objects.all()
|
||||
|
||||
|
||||
@ -191,6 +208,7 @@ class ACLExtendedRuleListView(generic.ObjectListView):
|
||||
"""
|
||||
Defines the list view for the ACLExtendedRule django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLExtendedRule.objects.all()
|
||||
table = tables.ACLExtendedRuleTable
|
||||
filterset = filtersets.ACLExtendedRuleFilterSet
|
||||
@ -201,6 +219,7 @@ class ACLExtendedRuleEditView(generic.ObjectEditView):
|
||||
"""
|
||||
Defines the edit view for the ACLExtendedRule django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLExtendedRule.objects.all()
|
||||
form = forms.ACLExtendedRuleForm
|
||||
|
||||
@ -209,8 +228,10 @@ class ACLExtendedRuleDeleteView(generic.ObjectDeleteView):
|
||||
"""
|
||||
Defines the delete view for the ACLExtendedRules django model.
|
||||
"""
|
||||
|
||||
queryset = models.ACLExtendedRule.objects.all()
|
||||
|
||||
|
||||
class ACLExtendedRuleBulkDeleteView(generic.BulkDeleteView):
|
||||
queryset = models.ACLExtendedRule.objects.all()
|
||||
filterset = filtersets.ACLExtendedRuleFilterSet
|
||||
|
||||
24
setup.py
24
setup.py
@ -1,20 +1,20 @@
|
||||
#import codecs
|
||||
#import os.path
|
||||
# import codecs
|
||||
# import os.path
|
||||
#
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
#
|
||||
#with open("README.md", "r") as fh:
|
||||
# with open("README.md", "r") as fh:
|
||||
# long_description = fh.read()
|
||||
#
|
||||
#
|
||||
#def read(rel_path):
|
||||
# def read(rel_path):
|
||||
# here = os.path.abspath(os.path.dirname(__file__))
|
||||
# with codecs.open(os.path.join(here, rel_path), 'r') as fp:
|
||||
# with codecs.open(os.path.join(here, rel_path), "r") as fp:
|
||||
# return fp.read()
|
||||
#
|
||||
#
|
||||
#def get_version(rel_path):
|
||||
# def get_version(rel_path):
|
||||
# for line in read(rel_path).splitlines():
|
||||
# if line.startswith('__version__'):
|
||||
# delim = '"' if '"' in line else "'"
|
||||
@ -24,13 +24,13 @@ from setuptools import find_packages, setup
|
||||
#
|
||||
|
||||
setup(
|
||||
name='netbox-access-lists',
|
||||
version='0.1.0',
|
||||
#version=get_version('netbox_access_lists/version.py'),
|
||||
description='A NetBox plugin for Access List management',
|
||||
#long_description=long_description,
|
||||
name="netbox-access-lists",
|
||||
version="0.1.0",
|
||||
# version=get_version("netbox_access_lists/version.py"),
|
||||
description="A NetBox plugin for Access List management",
|
||||
# long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
url='https://github.com/ryanmerolle/netbox-access-lists',
|
||||
url="https://github.com/ryanmerolle/netbox-access-lists",
|
||||
install_requires=[],
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user