Refactor crypto models (WIP)

This commit is contained in:
Jeremy Stretch 2023-11-20 17:07:48 -05:00
parent eba9677142
commit 6d55f54afd
21 changed files with 1512 additions and 399 deletions

View File

@ -216,6 +216,10 @@ VPN_MENU = Menu(
MenuGroup(
label=_('Security'),
items=(
get_model_item('vpn', 'ikeproposal', _('IKE Proposals')),
get_model_item('vpn', 'ikepolicy', _('IKE Policies')),
get_model_item('vpn', 'ipsecproposal', _('IPSec Proposals')),
get_model_item('vpn', 'ipsecpolicy', _('IPSec Policies')),
get_model_item('vpn', 'ipsecprofile', _('IPSec Profiles')),
),
),

View File

@ -0,0 +1,45 @@
{% extends 'generic/object.html' %}
{% load helpers %}
{% load plugins %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col col-md-6">
<div class="card">
<h5 class="card-header">{% trans "IKE Policy" %}</h5>
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "Name" %}</th>
<td>{{ object.name }}</td>
</tr>
<tr>
<th scope="row">{% trans "IKE Version" %}</th>
<td>{{ object.get_version_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "Mode" %}</th>
<td>{{ object.get_mode_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "Description" %}</th>
<td>{{ object.description|placeholder }}</td>
</tr>
</table>
</div>
</div>
{% plugin_left_page object %}
</div>
<div class="col col-md-6">
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %}
{% plugin_right_page object %}
</div>
</div>
<div class="row">
<div class="col col-md-12">
{% plugin_full_width_page object %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,57 @@
{% extends 'generic/object.html' %}
{% load helpers %}
{% load plugins %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col col-md-6">
<div class="card">
<h5 class="card-header">{% trans "IKE Proposal" %}</h5>
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "Name" %}</th>
<td>{{ object.name }}</td>
</tr>
<tr>
<th scope="row">{% trans "Authentication method" %}</th>
<td>{{ object.get_authentication_method_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "Encryption algorithm" %}</th>
<td>{{ object.get_encryption_algorithm_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "Authentication algorithm" %}</th>
<td>{{ object.get_authentication_algorithm_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "DH group" %}</th>
<td>{{ object.get_group_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "SA lifetime (seconds)" %}</th>
<td>{{ object.sa_lifetime|placeholder }}</td>
</tr>
<tr>
<th scope="row">{% trans "Description" %}</th>
<td>{{ object.description|placeholder }}</td>
</tr>
</table>
</div>
</div>
{% plugin_left_page object %}
</div>
<div class="col col-md-6">
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %}
{% plugin_right_page object %}
</div>
</div>
<div class="row">
<div class="col col-md-12">
{% plugin_full_width_page object %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,41 @@
{% extends 'generic/object.html' %}
{% load helpers %}
{% load plugins %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col col-md-6">
<div class="card">
<h5 class="card-header">{% trans "IPSec Policy" %}</h5>
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "Name" %}</th>
<td>{{ object.name }}</td>
</tr>
<tr>
<th scope="row">{% trans "PFS group" %}</th>
<td>{{ object.get_pfs_group_display|placeholder }}</td>
</tr>
<tr>
<th scope="row">{% trans "Description" %}</th>
<td>{{ object.description|placeholder }}</td>
</tr>
</table>
</div>
</div>
{% plugin_left_page object %}
</div>
<div class="col col-md-6">
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %}
{% plugin_right_page object %}
</div>
</div>
<div class="row">
<div class="col col-md-12">
{% plugin_full_width_page object %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,53 @@
{% extends 'generic/object.html' %}
{% load helpers %}
{% load plugins %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col col-md-6">
<div class="card">
<h5 class="card-header">{% trans "IPSec Proposal" %}</h5>
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "Name" %}</th>
<td>{{ object.name }}</td>
</tr>
<tr>
<th scope="row">{% trans "Encryption algorithm" %}</th>
<td>{{ object.get_encryption_algorithm_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "Authentication algorithm" %}</th>
<td>{{ object.get_authentication_algorithm_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "SA lifetime (seconds)" %}</th>
<td>{{ object.sa_lifetime_seconds|placeholder }}</td>
</tr>
<tr>
<th scope="row">{% trans "SA lifetime (KB)" %}</th>
<td>{{ object.sa_lifetime_data|placeholder }}</td>
</tr>
<tr>
<th scope="row">{% trans "Description" %}</th>
<td>{{ object.description|placeholder }}</td>
</tr>
</table>
</div>
</div>
{% plugin_left_page object %}
</div>
<div class="col col-md-6">
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %}
{% plugin_right_page object %}
</div>
</div>
<div class="row">
<div class="col col-md-12">
{% plugin_full_width_page object %}
</div>
</div>
{% endblock %}

View File

@ -4,7 +4,11 @@ from netbox.api.serializers import WritableNestedSerializer
from vpn import models
__all__ = (
'NestedIKEPolicySerializer',
'NestedIKEProposalSerializer',
'NestedIPSecPolicySerializer',
'NestedIPSecProfileSerializer',
'NestedIPSecProposalSerializer',
'NestedTunnelSerializer',
'NestedTunnelTerminationSerializer',
)
@ -30,6 +34,46 @@ class NestedTunnelTerminationSerializer(WritableNestedSerializer):
fields = ('id', 'url', 'display')
class NestedIKEProposalSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ikeproposal-detail'
)
class Meta:
model = models.IKEProposal
fields = ('id', 'url', 'display', 'name')
class NestedIKEPolicySerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ikepolicy-detail'
)
class Meta:
model = models.IKEProposal
fields = ('id', 'url', 'display', 'name')
class NestedIPSecProposalSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ipsecproposal-detail'
)
class Meta:
model = models.IPSecProposal
fields = ('id', 'url', 'display', 'name')
class NestedIPSecPolicySerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ipsecpolicy-detail'
)
class Meta:
model = models.IPSecProposal
fields = ('id', 'url', 'display', 'name')
class NestedIPSecProfileSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ipsecprofile-detail'

View File

@ -3,7 +3,7 @@ from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from ipam.api.nested_serializers import NestedIPAddressSerializer
from netbox.api.fields import ChoiceField, ContentTypeField
from netbox.api.fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
from netbox.api.serializers import NetBoxModelSerializer
from netbox.constants import NESTED_SERIALIZER_PREFIX
from tenancy.api.nested_serializers import NestedTenantSerializer
@ -13,7 +13,11 @@ from vpn.models import *
from .nested_serializers import *
__all__ = (
'IKEPolicySerializer',
'IKEProposalSerializer',
'IPSecPolicySerializer',
'IPSecProfileSerializer',
'IPSecProposalSerializer',
'TunnelSerializer',
'TunnelTerminationSerializer',
)
@ -41,8 +45,8 @@ class TunnelSerializer(NetBoxModelSerializer):
class Meta:
model = Tunnel
fields = (
'id', 'url', 'display', 'name', 'status', 'encapsulation', 'ipsec_profile', 'tenant', 'preshared_key',
'tunnel_id', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
'id', 'url', 'display', 'name', 'status', 'encapsulation', 'ipsec_profile', 'tenant', 'tunnel_id',
'comments', 'tags', 'custom_fields', 'created', 'last_updated',
)
@ -79,30 +83,130 @@ class TunnelTerminationSerializer(NetBoxModelSerializer):
return serializer(obj.interface, context=context).data
class IKEProposalSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ikeproposal-detail'
)
authentication_method = ChoiceField(
choices=AuthenticationMethodChoices
)
encryption_algorithm = ChoiceField(
choices=EncryptionAlgorithmChoices
)
authentication_algorithm = ChoiceField(
choices=AuthenticationAlgorithmChoices
)
group = ChoiceField(
choices=DHGroupChoices
)
class Meta:
model = IKEProposal
fields = (
'id', 'url', 'display', 'name', 'description', 'authentication_method', 'encryption_algorithm',
'authentication_algorithm', 'group', 'sa_lifetime', 'tags', 'custom_fields', 'created', 'last_updated',
)
class IKEPolicySerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ikepolicy-detail'
)
version = ChoiceField(
choices=IKEVersionChoices
)
mode = ChoiceField(
choices=IKEModeChoices
)
authentication_algorithm = ChoiceField(
choices=AuthenticationAlgorithmChoices
)
group = ChoiceField(
choices=DHGroupChoices
)
proposals = SerializedPKRelatedField(
queryset=IKEProposal.objects.all(),
serializer=NestedIKEProposalSerializer,
required=False,
many=True
)
class Meta:
model = IKEPolicy
fields = (
'id', 'url', 'display', 'name', 'description', 'version', 'mode', 'proposals', 'preshared_key',
'certificate', 'tags', 'custom_fields', 'created', 'last_updated',
)
class IPSecProposalSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ipsecproposal-detail'
)
encryption_algorithm = ChoiceField(
choices=EncryptionAlgorithmChoices
)
authentication_algorithm = ChoiceField(
choices=AuthenticationAlgorithmChoices
)
group = ChoiceField(
choices=DHGroupChoices
)
class Meta:
model = IPSecProposal
fields = (
'id', 'url', 'display', 'name', 'description', 'encryption_algorithm', 'authentication_algorithm',
'sa_lifetime_data', 'sa_lifetime_seconds', 'tags', 'custom_fields', 'created', 'last_updated',
)
class IPSecPolicySerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ipsecpolicy-detail'
)
proposals = SerializedPKRelatedField(
queryset=IPSecProposal.objects.all(),
serializer=NestedIPSecProposalSerializer,
required=False,
many=True
)
pfs_group = ChoiceField(
choices=DHGroupChoices
)
class Meta:
model = IPSecPolicy
fields = (
'id', 'url', 'display', 'name', 'description', 'proposals', 'pfs_group', 'tags', 'custom_fields', 'created',
'last_updated',
)
class IPSecProfileSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='vpn-api:ipsecprofile-detail'
)
protocol = ChoiceField(
choices=IPSecProtocolChoices
choices=IPSecModeChoices
)
ike_version = ChoiceField(
choices=IKEVersionChoices
)
phase1_encryption = ChoiceField(
choices=EncryptionChoices
choices=EncryptionAlgorithmChoices
)
phase1_authentication = ChoiceField(
choices=AuthenticationChoices
choices=AuthenticationAlgorithmChoices
)
phase1_group = ChoiceField(
choices=DHGroupChoices
)
phase2_encryption = ChoiceField(
choices=EncryptionChoices
choices=EncryptionAlgorithmChoices
)
phase2_authentication = ChoiceField(
choices=AuthenticationChoices
choices=AuthenticationAlgorithmChoices
)
phase2_group = ChoiceField(
choices=DHGroupChoices

View File

@ -3,6 +3,10 @@ from . import views
router = NetBoxRouter()
router.APIRootView = views.VPNRootView
router.register('ike-policies', views.IKEPolicyViewSet)
router.register('ike-proposals', views.IKEProposalViewSet)
router.register('ipsec-policies', views.IPSecPolicyViewSet)
router.register('ipsec-proposals', views.IPSecProposalViewSet)
router.register('ipsec-profiles', views.IPSecProfileViewSet)
router.register('tunnels', views.TunnelViewSet)
router.register('tunnel-terminations', views.TunnelTerminationViewSet)

View File

@ -7,7 +7,11 @@ from vpn.models import *
from . import serializers
__all__ = (
'IKEPolicyViewSet',
'IKEProposalViewSet',
'IPSecPolicyViewSet',
'IPSecProfileViewSet',
'IPSecProposalViewSet',
'TunnelTerminationViewSet',
'TunnelViewSet',
'VPNRootView',
@ -40,6 +44,30 @@ class TunnelTerminationViewSet(NetBoxModelViewSet):
filterset_class = filtersets.TunnelTerminationFilterSet
class IKEProposalViewSet(NetBoxModelViewSet):
queryset = IKEProposal.objects.all()
serializer_class = serializers.IKEProposalSerializer
filterset_class = filtersets.IKEProposalFilterSet
class IKEPolicyViewSet(NetBoxModelViewSet):
queryset = IKEPolicy.objects.all()
serializer_class = serializers.IKEPolicySerializer
filterset_class = filtersets.IKEPolicyFilterSet
class IPSecProposalViewSet(NetBoxModelViewSet):
queryset = IPSecProposal.objects.all()
serializer_class = serializers.IPSecProposalSerializer
filterset_class = filtersets.IPSecProposalFilterSet
class IPSecPolicyViewSet(NetBoxModelViewSet):
queryset = IKEPolicy.objects.all()
serializer_class = serializers.IPSecPolicySerializer
filterset_class = filtersets.IPSecPolicyFilterSet
class IPSecProfileViewSet(NetBoxModelViewSet):
queryset = IPSecProfile.objects.all()
serializer_class = serializers.IPSecProfileSerializer

View File

@ -59,19 +59,9 @@ class TunnelTerminationRoleChoices(ChoiceSet):
#
# IKE
# Crypto
#
class IPSecProtocolChoices(ChoiceSet):
PROTOCOL_ESP = 'esp'
PROTOCOL_AH = 'ah'
CHOICES = (
(PROTOCOL_ESP, 'ESP'),
(PROTOCOL_AH, 'AH'),
)
class IKEVersionChoices(ChoiceSet):
VERSION_1 = 1
VERSION_2 = 2
@ -82,7 +72,41 @@ class IKEVersionChoices(ChoiceSet):
)
class EncryptionChoices(ChoiceSet):
class IKEModeChoices(ChoiceSet):
AGGRESSIVE = 'aggressive'
MAIN = 'main'
CHOICES = (
(AGGRESSIVE, _('Aggressive')),
(MAIN, _('Main')),
)
class AuthenticationMethodChoices(ChoiceSet):
PRESHARED_KEYS = 'preshared-keys'
CERTIFICATES = 'certificates'
RSA_SIGNATURES = 'rsa-signatures'
DSA_SIGNATURES = 'dsa-signatures'
CHOICES = (
(PRESHARED_KEYS, _('Pre-shared keys')),
(CERTIFICATES, _('Certificates')),
(RSA_SIGNATURES, _('RSA signatures')),
(DSA_SIGNATURES, _('DSA signatures')),
)
class IPSecModeChoices(ChoiceSet):
ESP = 'esp'
AH = 'ah'
CHOICES = (
(ESP, 'ESP'),
(AH, 'AH'),
)
class EncryptionAlgorithmChoices(ChoiceSet):
ENCRYPTION_AES128_CBC = 'aes-128-cbc'
ENCRYPTION_AES128_GCM = 'aes-128-gcm'
ENCRYPTION_AES192_CBC = 'aes-192-cbc'
@ -104,7 +128,7 @@ class EncryptionChoices(ChoiceSet):
)
class AuthenticationChoices(ChoiceSet):
class AuthenticationAlgorithmChoices(ChoiceSet):
AUTH_HMAC_SHA1 = 'hmac-sha1'
AUTH_HMAC_SHA256 = 'hmac-sha256'
AUTH_HMAC_SHA384 = 'hmac-sha384'

View File

@ -6,12 +6,17 @@ from dcim.models import Interface
from ipam.models import IPAddress
from netbox.filtersets import NetBoxModelFilterSet
from tenancy.filtersets import TenancyFilterSet
from utilities.filters import ContentTypeFilter, MultiValueNumberFilter
from virtualization.models import VMInterface
from .choices import *
from .models import *
__all__ = (
'IKEPolicyFilterSet',
'IKEProposalFilterSet',
'IPSecPolicyFilterSet',
'IPSecProfileFilterSet',
'IPSecProposalFilterSet',
'TunnelFilterSet',
'TunnelTerminationFilterSet',
)
@ -37,7 +42,7 @@ class TunnelFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
class Meta:
model = Tunnel
fields = ['id', 'name', 'preshared_key', 'tunnel_id']
fields = ['id', 'name', 'tunnel_id']
def search(self, queryset, name, value):
if not value.strip():
@ -97,35 +102,129 @@ class TunnelTerminationFilterSet(NetBoxModelFilterSet):
fields = ['id']
class IPSecProfileFilterSet(NetBoxModelFilterSet):
protocol = django_filters.MultipleChoiceFilter(
choices=IPSecProtocolChoices
class IKEProposalFilterSet(NetBoxModelFilterSet):
authentication_method = django_filters.MultipleChoiceFilter(
choices=AuthenticationMethodChoices
)
ike_version = django_filters.MultipleChoiceFilter(
choices=IKEVersionChoices
encryption_algorithm = django_filters.MultipleChoiceFilter(
choices=EncryptionAlgorithmChoices
)
phase1_encryption = django_filters.MultipleChoiceFilter(
choices=EncryptionChoices
authentication_algorithm = django_filters.MultipleChoiceFilter(
choices=AuthenticationAlgorithmChoices
)
phase1_authentication = django_filters.MultipleChoiceFilter(
choices=AuthenticationChoices
)
phase1_group = django_filters.MultipleChoiceFilter(
choices=DHGroupChoices
)
phase2_encryption = django_filters.MultipleChoiceFilter(
choices=EncryptionChoices
)
phase2_authentication = django_filters.MultipleChoiceFilter(
choices=AuthenticationChoices
)
phase2_group = django_filters.MultipleChoiceFilter(
group = django_filters.MultipleChoiceFilter(
choices=DHGroupChoices
)
class Meta:
model = IKEProposal
fields = ['id', 'name', 'sa_lifetime']
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value) |
Q(description__icontains=value)
)
class IKEPolicyFilterSet(NetBoxModelFilterSet):
version = django_filters.MultipleChoiceFilter(
choices=IKEVersionChoices
)
mode = django_filters.MultipleChoiceFilter(
choices=IKEModeChoices
)
proposal_id = MultiValueNumberFilter(
field_name='proposals__id'
)
proposals = ContentTypeFilter()
class Meta:
model = IKEPolicy
fields = ['id', 'name']
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value) |
Q(description__icontains=value)
)
class IPSecProposalFilterSet(NetBoxModelFilterSet):
encryption_algorithm = django_filters.MultipleChoiceFilter(
choices=EncryptionAlgorithmChoices
)
authentication_algorithm = django_filters.MultipleChoiceFilter(
choices=AuthenticationAlgorithmChoices
)
class Meta:
model = IPSecProposal
fields = ['id', 'name', 'sa_lifetime_seconds', 'sa_lifetime_data']
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value) |
Q(description__icontains=value)
)
class IPSecPolicyFilterSet(NetBoxModelFilterSet):
pfs_group = django_filters.MultipleChoiceFilter(
choices=DHGroupChoices
)
proposal_id = MultiValueNumberFilter(
field_name='proposals__id'
)
proposals = ContentTypeFilter()
class Meta:
model = IPSecPolicy
fields = ['id', 'name']
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value) |
Q(description__icontains=value)
)
class IPSecProfileFilterSet(NetBoxModelFilterSet):
mode = django_filters.MultipleChoiceFilter(
choices=IPSecModeChoices
)
ike_policy_id = django_filters.ModelMultipleChoiceFilter(
queryset=IKEPolicy.objects.all(),
label=_('IKE policy (ID)'),
)
ike_policy = django_filters.ModelMultipleChoiceFilter(
field_name='ike_policy__name',
queryset=IKEPolicy.objects.all(),
to_field_name='name',
label=_('IKE policy (name)'),
)
ipsec_policy_id = django_filters.ModelMultipleChoiceFilter(
queryset=IPSecPolicy.objects.all(),
label=_('IPSec policy (ID)'),
)
ipsec_policy = django_filters.ModelMultipleChoiceFilter(
field_name='ipsec_policy__name',
queryset=IPSecPolicy.objects.all(),
to_field_name='name',
label=_('IPSec policy (name)'),
)
class Meta:
model = IPSecProfile
fields = ['id', 'name', 'phase1_sa_lifetime', 'phase2_sa_lifetime', 'phase2_sa_lifetime_data']
fields = ['id', 'name']
def search(self, queryset, name, value):
if not value.strip():

View File

@ -9,7 +9,11 @@ from vpn.choices import *
from vpn.models import *
__all__ = (
'IKEPolicyBulkEditForm',
'IKEProposalBulkEditForm',
'IPSecPolicyBulkEditForm',
'IPSecProfileBulkEditForm',
'IPSecProposalBulkEditForm',
'TunnelBulkEditForm',
'TunnelTerminationBulkEditForm',
)
@ -31,10 +35,6 @@ class TunnelBulkEditForm(NetBoxModelBulkEditForm):
label=_('IPSec profile'),
required=False
)
preshared_key = forms.CharField(
label=_('Pre-shared key'),
required=False
)
tenant = DynamicModelChoiceField(
label=_('Tenant'),
queryset=Tenant.objects.all(),
@ -54,11 +54,11 @@ class TunnelBulkEditForm(NetBoxModelBulkEditForm):
model = Tunnel
fieldsets = (
(_('Tunnel'), ('status', 'encapsulation', 'tunnel_id', 'description')),
(_('Security'), ('ipsec_profile', 'preshared_key')),
(_('Security'), ('ipsec_profile',)),
(_('Tenancy'), ('tenant',)),
)
nullable_fields = (
'ipsec_profile', 'preshared_key', 'tunnel_id', 'tenant', 'description', 'comments',
'ipsec_profile', 'tunnel_id', 'tenant', 'description', 'comments',
)
@ -75,61 +75,130 @@ class TunnelTerminationBulkEditForm(NetBoxModelBulkEditForm):
)
class IPSecProfileBulkEditForm(NetBoxModelBulkEditForm):
protocol = forms.ChoiceField(
label=_('Protocol'),
choices=add_blank_choice(IPSecProtocolChoices),
class IKEProposalBulkEditForm(NetBoxModelBulkEditForm):
authentication_method = forms.ChoiceField(
label=_('Authentication method'),
choices=add_blank_choice(AuthenticationMethodChoices),
required=False
)
ike_version = forms.ChoiceField(
label=_('IKE version'),
encryption_algorithm = forms.ChoiceField(
label=_('Encryption algorithm'),
choices=add_blank_choice(EncryptionAlgorithmChoices),
required=False
)
authentication_algorithm = forms.ChoiceField(
label=_('Authentication algorithm'),
choices=add_blank_choice(AuthenticationAlgorithmChoices),
required=False
)
group = forms.ChoiceField(
label=_('Group'),
choices=add_blank_choice(DHGroupChoices),
required=False
)
sa_lifetime = forms.IntegerField(
required=False
)
model = IKEProposal
fieldsets = (
(None, ('name', 'description')),
(_('Parameters'), (
'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group', 'sa_lifetime',
)),
)
nullable_fields = (
'description', 'sa_lifetime', 'comments',
)
class IKEPolicyBulkEditForm(NetBoxModelBulkEditForm):
version = forms.ChoiceField(
label=_('Version'),
choices=add_blank_choice(IKEVersionChoices),
required=False
)
mode = forms.ChoiceField(
label=_('Mode'),
choices=add_blank_choice(IKEModeChoices),
required=False
)
preshared_key = forms.CharField(
label=_('Pre-shared key'),
required=False
)
certificate = forms.CharField(
label=_('Certificate'),
required=False
)
model = IKEPolicy
fieldsets = (
(None, ('name', 'description')),
(_('Parameters'), (
'version', 'mode', 'preshared_key', 'certificate',
)),
)
nullable_fields = (
'description', 'preshared_key', 'certificate', 'comments',
)
class IPSecProposalBulkEditForm(NetBoxModelBulkEditForm):
encryption_algorithm = forms.ChoiceField(
label=_('Encryption algorithm'),
choices=add_blank_choice(EncryptionAlgorithmChoices),
required=False
)
authentication_algorithm = forms.ChoiceField(
label=_('Authentication algorithm'),
choices=add_blank_choice(AuthenticationAlgorithmChoices),
required=False
)
sa_lifetime_seconds = forms.IntegerField(
required=False
)
sa_lifetime_data = forms.IntegerField(
required=False
)
model = IPSecProposal
fieldsets = (
(None, ('name', 'description')),
(_('Parameters'), (
'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds', 'sa_lifetime_data',
)),
)
nullable_fields = (
'description', 'sa_lifetime_seconds', 'sa_lifetime_data', 'comments',
)
class IPSecPolicyBulkEditForm(NetBoxModelBulkEditForm):
pfs_group = forms.ChoiceField(
label=_('PFS group'),
choices=add_blank_choice(DHGroupChoices),
required=False
)
model = IPSecPolicy
fieldsets = (
(None, ('name', 'description')),
(_('Parameters'), (
'pfs_group',
)),
)
nullable_fields = (
'description', 'pfs_group', 'comments',
)
class IPSecProfileBulkEditForm(NetBoxModelBulkEditForm):
description = forms.CharField(
label=_('Description'),
max_length=200,
required=False
)
phase1_encryption = forms.ChoiceField(
label=_('Encryption'),
choices=add_blank_choice(EncryptionChoices),
required=False
)
phase1_authentication = forms.ChoiceField(
label=_('Authentication'),
choices=add_blank_choice(AuthenticationChoices),
required=False
)
phase1_group = forms.ChoiceField(
label=_('Group'),
choices=add_blank_choice(DHGroupChoices),
required=False
)
phase1_sa_lifetime = forms.IntegerField(
required=False
)
phase2_encryption = forms.ChoiceField(
label=_('Encryption'),
choices=add_blank_choice(EncryptionChoices),
required=False
)
phase2_authentication = forms.ChoiceField(
label=_('Authentication'),
choices=add_blank_choice(AuthenticationChoices),
required=False
)
phase2_group = forms.ChoiceField(
label=_('Group'),
choices=add_blank_choice(DHGroupChoices),
required=False
)
phase2_sa_lifetime = forms.IntegerField(
required=False
)
phase2_sa_lifetime_data = forms.IntegerField(
required=False
)
comments = CommentField()
model = IPSecProfile
@ -137,14 +206,7 @@ class IPSecProfileBulkEditForm(NetBoxModelBulkEditForm):
(_('Profile'), (
'protocol', 'ike_version', 'description',
)),
(_('Phase 1 Parameters'), (
'phase1_encryption', 'phase1_authentication', 'phase1_group', 'phase1_sa_lifetime',
)),
(_('Phase 2 Parameters'), (
'phase2_encryption', 'phase2_authentication', 'phase2_group', 'phase2_sa_lifetime',
'phase2_sa_lifetime_data',
)),
)
nullable_fields = (
'description', 'phase1_sa_lifetime', 'phase2_sa_lifetime', 'phase2_sa_lifetime_data', 'comments',
'description', 'comments',
)

View File

@ -10,7 +10,11 @@ from vpn.choices import *
from vpn.models import *
__all__ = (
'IKEPolicyImportForm',
'IKEProposalImportForm',
'IPSecPolicyImportForm',
'IPSecProfileImportForm',
'IPSecProposalImportForm',
'TunnelImportForm',
'TunnelTerminationImportForm',
)
@ -43,8 +47,8 @@ class TunnelImportForm(NetBoxModelImportForm):
class Meta:
model = Tunnel
fields = (
'name', 'status', 'encapsulation', 'ipsec_profile', 'tenant', 'preshared_key', 'tunnel_id', 'description',
'comments', 'tags',
'name', 'status', 'encapsulation', 'ipsec_profile', 'tenant', 'tunnel_id', 'description', 'comments',
'tags',
)
@ -108,46 +112,109 @@ class TunnelTerminationImportForm(NetBoxModelImportForm):
)
class IKEProposalImportForm(NetBoxModelImportForm):
authentication_method = CSVChoiceField(
label=_('Authentication method'),
choices=AuthenticationMethodChoices
)
encryption_algorithm = CSVChoiceField(
label=_('Encryption algorithm'),
choices=EncryptionAlgorithmChoices
)
authentication_algorithmn = CSVChoiceField(
label=_('Authentication algorithm'),
choices=AuthenticationAlgorithmChoices
)
group = CSVChoiceField(
label=_('Group'),
choices=DHGroupChoices
)
class Meta:
model = IKEProposal
fields = (
'name', 'description', 'authentication_method', 'encryption_algorithm', 'authentication_algorithmn',
'group', 'sa_lifetime', 'tags',
)
class IKEPolicyImportForm(NetBoxModelImportForm):
version = CSVChoiceField(
label=_('Version'),
choices=IKEVersionChoices
)
mode = CSVChoiceField(
label=_('Mode'),
choices=IKEModeChoices
)
# TODO: M2M field for proposals
class Meta:
model = IKEPolicy
fields = (
'name', 'description', 'version', 'mode', 'proposals', 'preshared_key', 'certificate', 'tags',
)
class IPSecProposalImportForm(NetBoxModelImportForm):
authentication_method = CSVChoiceField(
label=_('Authentication method'),
choices=AuthenticationMethodChoices
)
encryption_algorithm = CSVChoiceField(
label=_('Encryption algorithm'),
choices=EncryptionAlgorithmChoices
)
authentication_algorithmn = CSVChoiceField(
label=_('Authentication algorithm'),
choices=AuthenticationAlgorithmChoices
)
group = CSVChoiceField(
label=_('Group'),
choices=DHGroupChoices
)
class Meta:
model = IPSecProposal
fields = (
'name', 'description', 'encryption_algorithm', 'authentication_algorithmn', 'sa_lifetime_seconds',
'sa_lifetime_data', 'tags',
)
class IPSecPolicyImportForm(NetBoxModelImportForm):
pfs_group = CSVChoiceField(
label=_('PFS group'),
choices=DHGroupChoices
)
# TODO: M2M field for proposals
class Meta:
model = IPSecPolicy
fields = (
'name', 'description', 'proposals', 'pfs_group', 'tags',
)
class IPSecProfileImportForm(NetBoxModelImportForm):
protocol = CSVChoiceField(
label=_('Protocol'),
choices=IPSecProtocolChoices,
mode = CSVChoiceField(
label=_('Mode'),
choices=IPSecModeChoices,
help_text=_('IPSec protocol')
)
ike_version = CSVChoiceField(
label=_('IKE version'),
choices=IKEVersionChoices,
help_text=_('IKE version')
ike_policy = CSVModelChoiceField(
label=_('IKE policy'),
queryset=IKEPolicy.objects.all(),
to_field_name='name'
)
phase1_encryption = CSVChoiceField(
label=_('Phase 1 Encryption'),
choices=EncryptionChoices
)
phase1_authentication = CSVChoiceField(
label=_('Phase 1 Authentication'),
choices=AuthenticationChoices
)
phase1_group = CSVChoiceField(
label=_('Phase 1 Group'),
choices=DHGroupChoices
)
phase2_encryption = CSVChoiceField(
label=_('Phase 2 Encryption'),
choices=EncryptionChoices
)
phase2_authentication = CSVChoiceField(
label=_('Phase 2 Authentication'),
choices=AuthenticationChoices
)
phase2_group = CSVChoiceField(
label=_('Phase 2 Group'),
choices=DHGroupChoices
ipsec_policy = CSVModelChoiceField(
label=_('IPSec policy'),
queryset=IPSecPolicy.objects.all(),
to_field_name='name'
)
class Meta:
model = IPSecProfile
fields = (
'name', 'protocol', 'ike_version', 'phase1_encryption', 'phase1_authentication', 'phase1_group',
'phase1_sa_lifetime', 'phase2_encryption', 'phase2_authentication', 'phase2_group', 'phase2_sa_lifetime',
'phase2_sa_lifetime_data', 'description', 'comments', 'tags',
'name', 'ike_policy', 'ipsec_policy', 'description', 'comments', 'tags',
)

View File

@ -8,7 +8,11 @@ from vpn.choices import *
from vpn.models import *
__all__ = (
'IKEPolicyFilterForm',
'IKEProposalFilterForm',
'IPSecPolicyFilterForm',
'IPSecProfileFilterForm',
'IPSecProposalFilterForm',
'TunnelFilterForm',
'TunnelTerminationFilterForm',
)
@ -19,7 +23,7 @@ class TunnelFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
fieldsets = (
(None, ('q', 'filter_id', 'tag')),
(_('Tunnel'), ('status', 'encapsulation', 'tunnel_id')),
(_('Security'), ('ipsec_profile_id', 'preshared_key')),
(_('Security'), ('ipsec_profile_id',)),
(_('Tenancy'), ('tenant_group_id', 'tenant_id')),
)
status = forms.MultipleChoiceField(
@ -37,10 +41,6 @@ class TunnelFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
required=False,
label=_('IPSec profile')
)
preshared_key = forms.CharField(
required=False,
label=_('Pre-shared key')
)
tunnel_id = forms.IntegerField(
required=False,
label=_('Tunnel ID')
@ -67,6 +67,97 @@ class TunnelTerminationFilterForm(NetBoxModelFilterSetForm):
tag = TagFilterField(model)
class IKEProposalFilterForm(NetBoxModelFilterSetForm):
model = IKEProposal
fieldsets = (
(None, ('q', 'filter_id', 'tag')),
(_('Parameters'), ('authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group')),
)
authentication_method = forms.MultipleChoiceField(
label=_('Authentication method'),
choices=AuthenticationMethodChoices,
required=False
)
encryption_algorithm = forms.MultipleChoiceField(
label=_('Encryption algorithm'),
choices=EncryptionAlgorithmChoices,
required=False
)
authentication_algorithm = forms.MultipleChoiceField(
label=_('Authentication algorithm'),
choices=AuthenticationAlgorithmChoices,
required=False
)
group = forms.MultipleChoiceField(
label=_('Group'),
choices=DHGroupChoices,
required=False
)
tag = TagFilterField(model)
class IKEPolicyFilterForm(NetBoxModelFilterSetForm):
model = IKEPolicy
fieldsets = (
(None, ('q', 'filter_id', 'tag')),
(_('Parameters'), ('version', 'mode', 'proposal_id')),
)
version = forms.MultipleChoiceField(
label=_('IKE version'),
choices=IKEVersionChoices,
required=False
)
mode = forms.MultipleChoiceField(
label=_('Mode'),
choices=IKEModeChoices,
required=False
)
proposal_id = DynamicModelMultipleChoiceField(
queryset=IKEProposal.objects.all(),
required=False,
label=_('Proposal')
)
tag = TagFilterField(model)
class IPSecProposalFilterForm(NetBoxModelFilterSetForm):
model = IPSecProposal
fieldsets = (
(None, ('q', 'filter_id', 'tag')),
(_('Parameters'), ('encryption_algorithm', 'authentication_algorithm')),
)
encryption_algorithm = forms.MultipleChoiceField(
label=_('Encryption algorithm'),
choices=EncryptionAlgorithmChoices,
required=False
)
authentication_algorithm = forms.MultipleChoiceField(
label=_('Authentication algorithm'),
choices=AuthenticationAlgorithmChoices,
required=False
)
tag = TagFilterField(model)
class IPSecPolicyFilterForm(NetBoxModelFilterSetForm):
model = IPSecPolicy
fieldsets = (
(None, ('q', 'filter_id', 'tag')),
(_('Parameters'), ('proposal', 'pfs_group')),
)
proposal_id = DynamicModelMultipleChoiceField(
queryset=IKEProposal.objects.all(),
required=False,
label=_('Proposal')
)
pfs_group = forms.MultipleChoiceField(
label=_('Mode'),
choices=DHGroupChoices,
required=False
)
tag = TagFilterField(model)
class IPSecProfileFilterForm(NetBoxModelFilterSetForm):
model = IPSecProfile
fieldsets = (
@ -80,64 +171,19 @@ class IPSecProfileFilterForm(NetBoxModelFilterSetForm):
'phase2_sa_lifetime_data',
)),
)
protocol = forms.MultipleChoiceField(
label=_('Protocol'),
choices=IPSecProtocolChoices,
mode = forms.MultipleChoiceField(
label=_('Mode'),
choices=IPSecModeChoices,
required=False
)
ike_version = forms.MultipleChoiceField(
label=_('IKE version'),
choices=IKEVersionChoices,
required=False
)
ipsec_profile_id = DynamicModelMultipleChoiceField(
queryset=IPSecProfile.objects.all(),
ike_policy_id = DynamicModelMultipleChoiceField(
queryset=IKEPolicy.objects.all(),
required=False,
label=_('IPSec profile')
label=_('IKE policy')
)
phase1_encryption = forms.MultipleChoiceField(
label=_('Encryption'),
choices=EncryptionChoices,
required=False
)
phase1_authentication = forms.MultipleChoiceField(
label=_('Authentication'),
choices=AuthenticationChoices,
required=False
)
phase1_group = forms.MultipleChoiceField(
label=_('Group'),
choices=DHGroupChoices,
required=False
)
phase1_sa_lifetime = forms.IntegerField(
ipsec_policy_id = DynamicModelMultipleChoiceField(
queryset=IPSecPolicy.objects.all(),
required=False,
min_value=0,
label=_('SA lifetime')
)
phase2_encryption = forms.MultipleChoiceField(
label=_('Encryption'),
choices=EncryptionChoices,
required=False
)
phase2_authentication = forms.MultipleChoiceField(
label=_('Authentication'),
choices=AuthenticationChoices,
required=False
)
phase2_group = forms.MultipleChoiceField(
label=_('Group'),
choices=DHGroupChoices,
required=False
)
phase2_sa_lifetime = forms.IntegerField(
required=False,
min_value=0,
label=_('SA lifetime')
)
phase2_sa_lifetime_data = forms.IntegerField(
required=False,
min_value=0,
label=_('SA lifetime (data)')
label=_('IPSec policy')
)
tag = TagFilterField(model)

View File

@ -5,14 +5,18 @@ from dcim.models import Device, Interface
from ipam.models import IPAddress
from netbox.forms import NetBoxModelForm
from tenancy.forms import TenancyForm
from utilities.forms.fields import CommentField, DynamicModelChoiceField
from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField
from utilities.forms.widgets import HTMXSelect
from virtualization.models import VirtualMachine, VMInterface
from vpn.choices import *
from vpn.models import *
__all__ = (
'IKEPolicyForm',
'IKEProposalForm',
'IPSecPolicyForm',
'IPSecProfileForm',
'IPSecProposalForm',
'TunnelCreateForm',
'TunnelForm',
'TunnelTerminationForm',
@ -30,15 +34,15 @@ class TunnelForm(TenancyForm, NetBoxModelForm):
fieldsets = (
(_('Tunnel'), ('name', 'status', 'encapsulation', 'description', 'tunnel_id', 'tags')),
(_('Security'), ('ipsec_profile', 'preshared_key')),
(_('Security'), ('ipsec_profile',)),
(_('Tenancy'), ('tenant_group', 'tenant')),
)
class Meta:
model = Tunnel
fields = [
'name', 'status', 'encapsulation', 'description', 'tunnel_id', 'ipsec_profile', 'preshared_key',
'tenant_group', 'tenant', 'comments', 'tags',
'name', 'status', 'encapsulation', 'description', 'tunnel_id', 'ipsec_profile', 'tenant_group', 'tenant',
'comments', 'tags',
]
@ -111,7 +115,7 @@ class TunnelCreateForm(TunnelForm):
fieldsets = (
(_('Tunnel'), ('name', 'status', 'encapsulation', 'description', 'tunnel_id', 'tags')),
(_('Security'), ('ipsec_profile', 'preshared_key')),
(_('Security'), ('ipsec_profile',)),
(_('Tenancy'), ('tenant_group', 'tenant')),
(_('First Termination'), (
'termination1_role', 'termination1_type', 'termination1_parent', 'termination1_interface',
@ -264,26 +268,87 @@ class TunnelTerminationCreateForm(NetBoxModelForm):
self.instance.interface = self.cleaned_data['interface']
class IKEProposalForm(NetBoxModelForm):
fieldsets = (
(_('Proposal'), ('name', 'description', 'tags')),
(_('Parameters'), (
'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group', 'sa_lifetime',
)),
)
class Meta:
model = IKEProposal
fields = [
'name', 'description', 'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group',
'sa_lifetime', 'tags',
]
class IKEPolicyForm(NetBoxModelForm):
proposals = DynamicModelMultipleChoiceField(
queryset=IKEProposal.objects.all()
)
fieldsets = (
(_('Policy'), ('name', 'description', 'tags')),
(_('Parameters'), ('version', 'mode', 'proposals')),
(_('Authentication'), ('preshared_key', 'certificate')),
)
class Meta:
model = IKEPolicy
fields = [
'name', 'description', 'version', 'mode', 'proposals', 'preshared_key', 'certificate', 'tags',
]
class IPSecProposalForm(NetBoxModelForm):
fieldsets = (
(_('Proposal'), ('name', 'description', 'tags')),
(_('Parameters'), (
'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds', 'sa_lifetime_data',
)),
)
class Meta:
model = IPSecProposal
fields = [
'name', 'description', 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds',
'sa_lifetime_data', 'tags',
]
class IPSecPolicyForm(NetBoxModelForm):
proposals = DynamicModelMultipleChoiceField(
queryset=IPSecProposal.objects.all()
)
fieldsets = (
(_('Policy'), ('name', 'description', 'tags')),
(_('Parameters'), ('proposals', 'pfs_group')),
)
class Meta:
model = IPSecPolicy
fields = [
'name', 'description', 'proposals', 'pfs_group', 'tags',
]
class IPSecProfileForm(NetBoxModelForm):
comments = CommentField()
fieldsets = (
(_('Profile'), (
'name', 'protocol', 'ike_version', 'description', 'tags',
)),
(_('Phase 1 Parameters'), (
'phase1_encryption', 'phase1_authentication', 'phase1_group', 'phase1_sa_lifetime',
)),
(_('Phase 2 Parameters'), (
'phase2_encryption', 'phase2_authentication', 'phase2_group', 'phase2_sa_lifetime',
'phase2_sa_lifetime_data',
'name', 'mode', 'description', 'tags',
)),
(_('Policies'), ('ipsec_policy', 'description', 'tags')),
)
class Meta:
model = IPSecProfile
fields = [
'name', 'protocol', 'ike_version', 'phase1_encryption', 'phase1_authentication', 'phase1_group',
'phase1_sa_lifetime', 'phase2_encryption', 'phase2_authentication', 'phase2_group', 'phase2_sa_lifetime',
'phase2_sa_lifetime_data', 'description', 'comments', 'tags',
'name', 'description', 'mode', 'ipsec_policy', 'description', 'comments', 'tags',
]

View File

@ -1,98 +0,0 @@
# Generated by Django 4.2.7 on 2023-11-15 19:50
from django.db import migrations, models
import django.db.models.deletion
import taggit.managers
import utilities.json
class Migration(migrations.Migration):
initial = True
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('tenancy', '0011_contactassignment_tags'),
('ipam', '0067_ipaddress_index_host'),
('extras', '0099_cachedvalue_ordering'),
]
operations = [
migrations.CreateModel(
name='IPSecProfile',
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=utilities.json.CustomFieldJSONEncoder)),
('description', models.CharField(blank=True, max_length=200)),
('comments', models.TextField(blank=True)),
('name', models.CharField(max_length=100, unique=True)),
('protocol', models.CharField()),
('ike_version', models.PositiveSmallIntegerField(default=2)),
('phase1_encryption', models.CharField()),
('phase1_authentication', models.CharField()),
('phase1_group', models.PositiveSmallIntegerField()),
('phase1_sa_lifetime', models.PositiveIntegerField(blank=True, null=True)),
('phase2_encryption', models.CharField()),
('phase2_authentication', models.CharField()),
('phase2_group', models.PositiveSmallIntegerField()),
('phase2_sa_lifetime', models.PositiveIntegerField(blank=True, null=True)),
('phase2_sa_lifetime_data', models.PositiveIntegerField(blank=True, null=True)),
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
],
options={
'verbose_name': 'tunnel',
'verbose_name_plural': 'tunnels',
'ordering': ('name',),
},
),
migrations.CreateModel(
name='Tunnel',
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=utilities.json.CustomFieldJSONEncoder)),
('description', models.CharField(blank=True, max_length=200)),
('comments', models.TextField(blank=True)),
('name', models.CharField(max_length=100, unique=True)),
('status', models.CharField(default='active', max_length=50)),
('encapsulation', models.CharField(max_length=50)),
('preshared_key', models.TextField(blank=True)),
('tunnel_id', models.PositiveBigIntegerField(blank=True, null=True)),
('ipsec_profile', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tunnels', to='vpn.ipsecprofile')),
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tunnels', to='tenancy.tenant')),
],
options={
'verbose_name': 'tunnel',
'verbose_name_plural': 'tunnels',
'ordering': ('name',),
},
),
migrations.CreateModel(
name='TunnelTermination',
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=utilities.json.CustomFieldJSONEncoder)),
('role', models.CharField(default='peer', max_length=50)),
('interface_id', models.PositiveBigIntegerField(blank=True, null=True)),
('interface_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')),
('outside_ip', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tunnel_termination', to='ipam.ipaddress')),
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
('tunnel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='vpn.tunnel')),
],
options={
'verbose_name': 'tunnel termination',
'verbose_name_plural': 'tunnel terminations',
'ordering': ('tunnel', 'role', 'pk'),
},
),
migrations.AddConstraint(
model_name='tunneltermination',
constraint=models.UniqueConstraint(fields=('interface_type', 'interface_id'), name='vpn_tunneltermination_interface', violation_error_message='An interface may be terminated to only one tunnel at a time.'),
),
]

View File

@ -2,88 +2,228 @@ from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from netbox.models import PrimaryModel
from netbox.models import NetBoxModel, PrimaryModel
from vpn.choices import *
__all__ = (
'IKEPolicy',
'IKEProposal',
'IPSecPolicy',
'IPSecProfile',
'IPSecProposal',
)
#
# IKE
#
class IKEProposal(NetBoxModel):
name = models.CharField(
verbose_name=_('name'),
max_length=100,
unique=True
)
description = models.CharField(
verbose_name=_('description'),
max_length=200,
blank=True
)
authentication_method = models.CharField(
verbose_name=('authentication method'),
choices=AuthenticationMethodChoices
)
encryption_algorithm = models.CharField(
verbose_name=_('encryption algorithm'),
choices=EncryptionAlgorithmChoices
)
authentication_algorithm = models.CharField(
verbose_name=_('authentication algorithm'),
choices=AuthenticationAlgorithmChoices
)
group = models.PositiveSmallIntegerField(
verbose_name=_('group'),
choices=DHGroupChoices,
help_text=_('Diffie-Hellman group ID')
)
sa_lifetime = models.PositiveIntegerField(
verbose_name=_('SA lifetime'),
blank=True,
null=True,
help_text=_('Security association lifetime (in seconds)')
)
class Meta:
ordering = ('name',)
verbose_name = _('IKE proposal')
verbose_name_plural = _('IKE proposals')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('vpn:ikeproposal', args=[self.pk])
class IKEPolicy(NetBoxModel):
name = models.CharField(
verbose_name=_('name'),
max_length=100,
unique=True
)
description = models.CharField(
verbose_name=_('description'),
max_length=200,
blank=True
)
version = models.PositiveSmallIntegerField(
verbose_name=_('version'),
choices=IKEVersionChoices,
default=IKEVersionChoices.VERSION_2
)
mode = models.CharField(
verbose_name=_('mode'),
choices=IKEModeChoices
)
proposals = models.ManyToManyField(
to='vpn.IKEProposal',
related_name='ike_policies',
verbose_name=_('proposals')
)
preshared_key = models.TextField(
verbose_name=_('pre-shared key'),
blank=True
)
certificate = models.TextField(
verbose_name=_('certificate'),
blank=True
)
class Meta:
ordering = ('name',)
verbose_name = _('IKE policy')
verbose_name_plural = _('IKE policies')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('vpn:ikeprofile', args=[self.pk])
#
# IPSec
#
class IPSecProposal(NetBoxModel):
name = models.CharField(
verbose_name=_('name'),
max_length=100,
unique=True
)
description = models.CharField(
verbose_name=_('description'),
max_length=200,
blank=True
)
encryption_algorithm = models.CharField(
verbose_name=_('encryption'),
choices=EncryptionAlgorithmChoices
)
authentication_algorithm = models.CharField(
verbose_name=_('authentication'),
choices=AuthenticationAlgorithmChoices
)
sa_lifetime_seconds = models.PositiveIntegerField(
verbose_name=_('SA lifetime (seconds)'),
blank=True,
null=True,
help_text=_('Security association lifetime (seconds)')
)
sa_lifetime_data = models.PositiveIntegerField(
verbose_name=_('SA lifetime (KB)'),
blank=True,
null=True,
help_text=_('Security association lifetime (in kilobytes)')
)
class Meta:
ordering = ('name',)
verbose_name = _('IPSec proposal')
verbose_name_plural = _('IPSec proposals')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('vpn:ipsecproposal', args=[self.pk])
class IPSecPolicy(NetBoxModel):
name = models.CharField(
verbose_name=_('name'),
max_length=100,
unique=True
)
description = models.CharField(
verbose_name=_('description'),
max_length=200,
blank=True
)
proposals = models.ManyToManyField(
to='vpn.IPSecProposal',
related_name='ipsec_policies',
verbose_name=_('proposals')
)
pfs_group = models.PositiveSmallIntegerField(
verbose_name=_('PFS group'),
choices=DHGroupChoices,
blank=True,
null=True,
help_text=_('Diffie-Hellman group for Perfect Forward Secrecy')
)
class Meta:
ordering = ('name',)
verbose_name = _('IPSec policy')
verbose_name_plural = _('IPSec policies')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('vpn:ipsecpolicy', args=[self.pk])
class IPSecProfile(PrimaryModel):
name = models.CharField(
verbose_name=_('name'),
max_length=100,
unique=True
)
protocol = models.CharField(
verbose_name=_('protocol'),
choices=IPSecProtocolChoices
mode = models.CharField(
verbose_name=_('mode'),
choices=IPSecModeChoices
)
ike_version = models.PositiveSmallIntegerField(
verbose_name=_('IKE version'),
choices=IKEVersionChoices,
default=IKEVersionChoices.VERSION_2
ike_policy = models.ForeignKey(
to='vpn.IKEPolicy',
on_delete=models.PROTECT,
related_name='ipsec_profiles'
)
# Phase 1 parameters
phase1_encryption = models.CharField(
verbose_name=_('phase 1 encryption'),
choices=EncryptionChoices
ipsec_policy = models.ForeignKey(
to='vpn.IPSecPolicy',
on_delete=models.PROTECT,
related_name='ipsec_profiles'
)
phase1_authentication = models.CharField(
verbose_name=_('phase 1 authentication'),
choices=AuthenticationChoices
)
phase1_group = models.PositiveSmallIntegerField(
verbose_name=_('phase 1 group'),
choices=DHGroupChoices,
help_text=_('Diffie-Hellman group')
)
phase1_sa_lifetime = models.PositiveIntegerField(
verbose_name=_('phase 1 SA lifetime'),
blank=True,
null=True,
help_text=_('Security association lifetime (in seconds)')
)
# Phase 2 parameters
phase2_encryption = models.CharField(
verbose_name=_('phase 2 encryption'),
choices=EncryptionChoices
)
phase2_authentication = models.CharField(
verbose_name=_('phase 2 authentication'),
choices=AuthenticationChoices
)
phase2_group = models.PositiveSmallIntegerField(
verbose_name=_('phase 2 group'),
choices=DHGroupChoices,
help_text=_('Diffie-Hellman group')
)
phase2_sa_lifetime = models.PositiveIntegerField(
verbose_name=_('phase 2 SA lifetime (seconds)'),
blank=True,
null=True,
help_text=_('Security association lifetime (seconds)')
)
phase2_sa_lifetime_data = models.PositiveIntegerField(
verbose_name=_('phase 2 SA lifetime (KB)'),
blank=True,
null=True,
help_text=_('Security association lifetime (in kilobytes)')
)
# TODO: Add PFS group?
clone_fields = (
'protocol', 'ike_version', 'phase1_encryption', 'phase1_authentication', 'phase1_group', 'phase1_sa_lifetime',
'phase2_encryption', 'phase2_authentication', 'phase2_group', 'phase2_sa_lifetime', 'phase2_sa_lifetime_data',
'mode', 'ike_policy', 'ipsec_policy',
)
class Meta:
ordering = ('name',)
verbose_name = _('tunnel')
verbose_name_plural = _('tunnels')
verbose_name = _('IPSec profile')
verbose_name_plural = _('IPSec profiles')
def __str__(self):
return self.name

View File

@ -45,10 +45,6 @@ class Tunnel(PrimaryModel):
blank=True,
null=True
)
preshared_key = models.TextField(
verbose_name=_('pre-shared key'),
blank=True
)
tunnel_id = models.PositiveBigIntegerField(
verbose_name=_('tunnel ID'),
blank=True,

View File

@ -1,5 +1,4 @@
import django_tables2 as tables
from django.contrib.contenttypes.fields import GenericRelation
from django.utils.translation import gettext_lazy as _
from django_tables2.utils import Accessor
@ -8,6 +7,10 @@ from netbox.tables import NetBoxTable, columns
from vpn.models import *
__all__ = (
'IKEPolicyTable',
'IKEProposalTable',
'IPSecPolicyTable',
'IPSecProposalTable',
'IPSecProfileTable',
'TunnelTable',
'TunnelTerminationTable',
@ -42,8 +45,8 @@ class TunnelTable(TenancyColumnsMixin, NetBoxTable):
class Meta(NetBoxTable.Meta):
model = Tunnel
fields = (
'pk', 'id', 'name', 'status', 'encapsulation', 'ipsec_profile', 'tenant', 'tenant_group', 'preshared_key',
'tunnel_id', 'termination_count', 'description', 'comments', 'tags', 'created', 'last_updated',
'pk', 'id', 'name', 'status', 'encapsulation', 'ipsec_profile', 'tenant', 'tenant_group', 'tunnel_id',
'termination_count', 'description', 'comments', 'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'status', 'encapsulation', 'tenant', 'terminations_count')
@ -89,47 +92,164 @@ class TunnelTerminationTable(TenancyColumnsMixin, NetBoxTable):
default_columns = ('pk', 'tunnel', 'role', 'interface_parent', 'interface', 'ip_addresses', 'outside_ip')
class IPSecProfileTable(TenancyColumnsMixin, NetBoxTable):
class IKEProposalTable(NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
linkify=True
)
protocol = columns.ChoiceFieldColumn(
verbose_name=_('Protocol')
authentication_method = columns.ChoiceFieldColumn(
verbose_name=_('Authentication Method')
)
ike_version = columns.ChoiceFieldColumn(
verbose_name=_('IKE Version')
encryption_algorithm = columns.ChoiceFieldColumn(
verbose_name=_('Encryption Algorithm')
)
phase1_encryption = columns.ChoiceFieldColumn(
verbose_name=_('Phase 1 Encryption')
authentication_algorithm = columns.ChoiceFieldColumn(
verbose_name=_('Authentication Algorithm')
)
phase1_authentication = columns.ChoiceFieldColumn(
verbose_name=_('Phase 1 Authentication')
group = columns.ChoiceFieldColumn(
verbose_name=_('Group')
)
phase1_group = columns.ChoiceFieldColumn(
verbose_name=_('Phase 1 Group')
sa_lifetime = tables.Column(
verbose_name=_('SA Lifetime')
)
phase2_encryption = columns.ChoiceFieldColumn(
verbose_name=_('Phase 2 Encryption')
tags = columns.TagColumn(
url_name='vpn:ikeproposal_list'
)
phase2_authentication = columns.ChoiceFieldColumn(
verbose_name=_('Phase 2 Authentication')
class Meta(NetBoxTable.Meta):
model = IKEProposal
fields = (
'pk', 'id', 'name', 'authentication_method', 'encryption_algorithm', 'authentication_algorithm',
'group', 'sa_lifetime', 'description', 'tags', 'created', 'last_updated',
)
phase2_group = columns.ChoiceFieldColumn(
verbose_name=_('Phase 2 Group')
default_columns = (
'pk', 'name', 'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group',
'sa_lifetime', 'description',
)
class IKEPolicyTable(NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
linkify=True
)
version = columns.ChoiceFieldColumn(
verbose_name=_('Version')
)
mode = columns.ChoiceFieldColumn(
verbose_name=_('Mode')
)
proposals = tables.ManyToManyColumn(
linkify_item=True,
verbose_name=_('Proposals')
)
preshared_key = tables.Column(
verbose_name=_('Pre-shared Key')
)
certificate = tables.Column(
verbose_name=_('Certificate')
)
tags = columns.TagColumn(
url_name='vpn:ikepolicy_list'
)
class Meta(NetBoxTable.Meta):
model = IKEPolicy
fields = (
'pk', 'id', 'name', 'version', 'mode', 'proposals', 'preshared_key', 'certificate', 'description', 'tags',
'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'version', 'mode', 'proposals', 'description',
)
class IPSecProposalTable(NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
linkify=True
)
encryption_algorithm = columns.ChoiceFieldColumn(
verbose_name=_('Encryption Algorithm')
)
authentication_algorithm = columns.ChoiceFieldColumn(
verbose_name=_('Authentication Algorithm')
)
sa_lifetime_seconds = tables.Column(
verbose_name=_('SA Lifetime (Seconds)')
)
sa_lifetime_data = tables.Column(
verbose_name=_('SA Lifetime (KB)')
)
tags = columns.TagColumn(
url_name='vpn:ipsecproposal_list'
)
class Meta(NetBoxTable.Meta):
model = IPSecProposal
fields = (
'pk', 'id', 'name', 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds',
'sa_lifetime_data', 'description', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds',
'sa_lifetime_data', 'description',
)
class IPSecPolicyTable(NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
linkify=True
)
proposals = tables.ManyToManyColumn(
linkify_item=True,
verbose_name=_('Proposals')
)
pfs_group = columns.ChoiceFieldColumn(
verbose_name=_('PFS Group')
)
tags = columns.TagColumn(
url_name='vpn:ipsecpolicy_list'
)
class Meta(NetBoxTable.Meta):
model = IPSecPolicy
fields = (
'pk', 'id', 'name', 'proposals', 'pfs_group', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'proposals', 'pfs_group', 'description',
)
class IPSecProfileTable(NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
linkify=True
)
mode = columns.ChoiceFieldColumn(
verbose_name=_('Mode')
)
ike_policy = tables.Column(
linkify=True,
verbose_name=_('IKE Policy')
)
ipsec_policy = tables.Column(
linkify=True,
verbose_name=_('IPSec Policy')
)
comments = columns.MarkdownColumn(
verbose_name=_('Comments'),
)
tags = columns.TagColumn(
url_name='vpn:tunnel_list'
url_name='vpn:ipsecprofile_list'
)
class Meta(NetBoxTable.Meta):
model = IPSecProfile
fields = (
'pk', 'id', 'name', 'protocol', 'ike_version', 'phase1_encryption', 'phase1_authentication', 'phase1_group',
'phase1_sa_lifetime', 'phase2_encryption', 'phase2_authentication', 'phase2_group', 'phase2_sa_lifetime',
'phase2_sa_lifetime_data', 'description', 'comments', 'tags', 'created', 'last_updated',
'pk', 'id', 'name', 'mode', 'ike_policy', 'ipsec_policy', 'description', 'comments', 'tags', 'created',
'last_updated',
)
default_columns = ('pk', 'name', 'protocol', 'ike_version', 'description')
default_columns = ('pk', 'name', 'mode', 'ike_policy', 'ipsec_policy', 'description')

View File

@ -22,6 +22,38 @@ urlpatterns = [
path('tunnel-terminations/delete/', views.TunnelTerminationBulkDeleteView.as_view(), name='tunneltermination_bulk_delete'),
path('tunnel-terminations/<int:pk>/', include(get_model_urls('vpn', 'tunneltermination'))),
# IKE proposals
path('ike-proposals/', views.IKEProposalListView.as_view(), name='ikeproposal_list'),
path('ike-proposals/add/', views.IKEProposalEditView.as_view(), name='ikeproposal_add'),
path('ike-proposals/import/', views.IKEProposalBulkImportView.as_view(), name='ikeproposal_import'),
path('ike-proposals/edit/', views.IKEProposalBulkEditView.as_view(), name='ikeproposal_bulk_edit'),
path('ike-proposals/delete/', views.IKEProposalBulkDeleteView.as_view(), name='ikeproposal_bulk_delete'),
path('ike-proposals/<int:pk>/', include(get_model_urls('vpn', 'ikeproposal'))),
# IKE policies
path('ike-policys/', views.IKEPolicyListView.as_view(), name='ikepolicy_list'),
path('ike-policys/add/', views.IKEPolicyEditView.as_view(), name='ikepolicy_add'),
path('ike-policys/import/', views.IKEPolicyBulkImportView.as_view(), name='ikepolicy_import'),
path('ike-policys/edit/', views.IKEPolicyBulkEditView.as_view(), name='ikepolicy_bulk_edit'),
path('ike-policys/delete/', views.IKEPolicyBulkDeleteView.as_view(), name='ikepolicy_bulk_delete'),
path('ike-policys/<int:pk>/', include(get_model_urls('vpn', 'ikepolicy'))),
# IPSec proposals
path('ipsec-proposals/', views.IPSecProposalListView.as_view(), name='ipsecproposal_list'),
path('ipsec-proposals/add/', views.IPSecProposalEditView.as_view(), name='ipsecproposal_add'),
path('ipsec-proposals/import/', views.IPSecProposalBulkImportView.as_view(), name='ipsecproposal_import'),
path('ipsec-proposals/edit/', views.IPSecProposalBulkEditView.as_view(), name='ipsecproposal_bulk_edit'),
path('ipsec-proposals/delete/', views.IPSecProposalBulkDeleteView.as_view(), name='ipsecproposal_bulk_delete'),
path('ipsec-proposals/<int:pk>/', include(get_model_urls('vpn', 'ipsecproposal'))),
# IPSec policies
path('ipsec-policys/', views.IPSecPolicyListView.as_view(), name='ipsecpolicy_list'),
path('ipsec-policys/add/', views.IPSecPolicyEditView.as_view(), name='ipsecpolicy_add'),
path('ipsec-policys/import/', views.IPSecPolicyBulkImportView.as_view(), name='ipsecpolicy_import'),
path('ipsec-policys/edit/', views.IPSecPolicyBulkEditView.as_view(), name='ipsecpolicy_bulk_edit'),
path('ipsec-policys/delete/', views.IPSecPolicyBulkDeleteView.as_view(), name='ipsecpolicy_bulk_delete'),
path('ipsec-policys/<int:pk>/', include(get_model_urls('vpn', 'ipsecpolicy'))),
# IPSec profiles
path('ipsec-profiles/', views.IPSecProfileListView.as_view(), name='ipsecprofile_list'),
path('ipsec-profiles/add/', views.IPSecProfileEditView.as_view(), name='ipsecprofile_add'),

View File

@ -112,6 +112,186 @@ class TunnelTerminationBulkDeleteView(generic.BulkDeleteView):
table = tables.TunnelTerminationTable
#
# IKE proposals
#
class IKEProposalListView(generic.ObjectListView):
queryset = IKEProposal.objects.all()
filterset = filtersets.IKEProposalFilterSet
filterset_form = forms.IKEProposalFilterForm
table = tables.IKEProposalTable
@register_model_view(IKEProposal)
class IKEProposalView(generic.ObjectView):
queryset = IKEProposal.objects.all()
@register_model_view(IKEProposal, 'edit')
class IKEProposalEditView(generic.ObjectEditView):
queryset = IKEProposal.objects.all()
form = forms.IKEProposalForm
@register_model_view(IKEProposal, 'delete')
class IKEProposalDeleteView(generic.ObjectDeleteView):
queryset = IKEProposal.objects.all()
class IKEProposalBulkImportView(generic.BulkImportView):
queryset = IKEProposal.objects.all()
model_form = forms.IKEProposalImportForm
class IKEProposalBulkEditView(generic.BulkEditView):
queryset = IKEProposal.objects.all()
filterset = filtersets.IKEProposalFilterSet
table = tables.IKEProposalTable
form = forms.IKEProposalBulkEditForm
class IKEProposalBulkDeleteView(generic.BulkDeleteView):
queryset = IKEProposal.objects.all()
filterset = filtersets.IKEProposalFilterSet
table = tables.IKEProposalTable
#
# IKE policies
#
class IKEPolicyListView(generic.ObjectListView):
queryset = IKEPolicy.objects.all()
filterset = filtersets.IKEPolicyFilterSet
filterset_form = forms.IKEPolicyFilterForm
table = tables.IKEPolicyTable
@register_model_view(IKEPolicy)
class IKEPolicyView(generic.ObjectView):
queryset = IKEPolicy.objects.all()
@register_model_view(IKEPolicy, 'edit')
class IKEPolicyEditView(generic.ObjectEditView):
queryset = IKEPolicy.objects.all()
form = forms.IKEPolicyForm
@register_model_view(IKEPolicy, 'delete')
class IKEPolicyDeleteView(generic.ObjectDeleteView):
queryset = IKEPolicy.objects.all()
class IKEPolicyBulkImportView(generic.BulkImportView):
queryset = IKEPolicy.objects.all()
model_form = forms.IKEPolicyImportForm
class IKEPolicyBulkEditView(generic.BulkEditView):
queryset = IKEPolicy.objects.all()
filterset = filtersets.IKEPolicyFilterSet
table = tables.IKEPolicyTable
form = forms.IKEPolicyBulkEditForm
class IKEPolicyBulkDeleteView(generic.BulkDeleteView):
queryset = IKEPolicy.objects.all()
filterset = filtersets.IKEPolicyFilterSet
table = tables.IKEPolicyTable
#
# IPSec proposals
#
class IPSecProposalListView(generic.ObjectListView):
queryset = IPSecProposal.objects.all()
filterset = filtersets.IPSecProposalFilterSet
filterset_form = forms.IPSecProposalFilterForm
table = tables.IPSecProposalTable
@register_model_view(IPSecProposal)
class IPSecProposalView(generic.ObjectView):
queryset = IPSecProposal.objects.all()
@register_model_view(IPSecProposal, 'edit')
class IPSecProposalEditView(generic.ObjectEditView):
queryset = IPSecProposal.objects.all()
form = forms.IPSecProposalForm
@register_model_view(IPSecProposal, 'delete')
class IPSecProposalDeleteView(generic.ObjectDeleteView):
queryset = IPSecProposal.objects.all()
class IPSecProposalBulkImportView(generic.BulkImportView):
queryset = IPSecProposal.objects.all()
model_form = forms.IPSecProposalImportForm
class IPSecProposalBulkEditView(generic.BulkEditView):
queryset = IPSecProposal.objects.all()
filterset = filtersets.IPSecProposalFilterSet
table = tables.IPSecProposalTable
form = forms.IPSecProposalBulkEditForm
class IPSecProposalBulkDeleteView(generic.BulkDeleteView):
queryset = IPSecProposal.objects.all()
filterset = filtersets.IPSecProposalFilterSet
table = tables.IPSecProposalTable
#
# IPSec policies
#
class IPSecPolicyListView(generic.ObjectListView):
queryset = IPSecPolicy.objects.all()
filterset = filtersets.IPSecPolicyFilterSet
filterset_form = forms.IPSecPolicyFilterForm
table = tables.IPSecPolicyTable
@register_model_view(IPSecPolicy)
class IPSecPolicyView(generic.ObjectView):
queryset = IPSecPolicy.objects.all()
@register_model_view(IPSecPolicy, 'edit')
class IPSecPolicyEditView(generic.ObjectEditView):
queryset = IPSecPolicy.objects.all()
form = forms.IPSecPolicyForm
@register_model_view(IPSecPolicy, 'delete')
class IPSecPolicyDeleteView(generic.ObjectDeleteView):
queryset = IPSecPolicy.objects.all()
class IPSecPolicyBulkImportView(generic.BulkImportView):
queryset = IPSecPolicy.objects.all()
model_form = forms.IPSecPolicyImportForm
class IPSecPolicyBulkEditView(generic.BulkEditView):
queryset = IPSecPolicy.objects.all()
filterset = filtersets.IPSecPolicyFilterSet
table = tables.IPSecPolicyTable
form = forms.IPSecPolicyBulkEditForm
class IPSecPolicyBulkDeleteView(generic.BulkDeleteView):
queryset = IPSecPolicy.objects.all()
filterset = filtersets.IPSecPolicyFilterSet
table = tables.IPSecPolicyTable
#
# IPSec profiles
#