Add UI view tests

This commit is contained in:
Jeremy Stretch 2023-11-21 16:04:33 -05:00
parent f600f908cf
commit c814e763a1
7 changed files with 629 additions and 54 deletions

View File

@ -0,0 +1,55 @@
{% 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 "Tunnel Termination" %}</h5>
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "Tunnel" %}</th>
<td>{{ object.tunnel|linkify }}</td>
</tr>
<tr>
<th scope="row">{% trans "Role" %}</th>
<td>{{ object.get_role_display }}</td>
</tr>
<tr>
<th scope="row">
{% if object.interface.device %}
{% trans "Device" %}
{% elif object.interface.virtual_machine %}
{% trans "Virtual Machine" %}
{% endif %}
</th>
<td>{{ object.interface.parent_object|linkify }}</td>
</tr>
<tr>
<th scope="row">{% trans "Interface" %}</th>
<td>{{ object.interface|linkify }}</td>
</tr>
<tr>
<th scope="row">{% trans "Outside IP" %}</th>
<td>{{ object.outside_ip|linkify|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,7 @@ from dcim.models import Device, Interface
from ipam.models import IPAddress from ipam.models import IPAddress
from netbox.forms import NetBoxModelImportForm from netbox.forms import NetBoxModelImportForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField from utilities.forms.fields import CSVChoiceField, CSVModelChoiceField, CSVModelMultipleChoiceField
from virtualization.models import VirtualMachine, VMInterface from virtualization.models import VirtualMachine, VMInterface
from vpn.choices import * from vpn.choices import *
from vpn.models import * from vpn.models import *
@ -34,6 +34,7 @@ class TunnelImportForm(NetBoxModelImportForm):
ipsec_profile = CSVModelChoiceField( ipsec_profile = CSVModelChoiceField(
label=_('IPSec profile'), label=_('IPSec profile'),
queryset=IPSecProfile.objects.all(), queryset=IPSecProfile.objects.all(),
required=False,
to_field_name='name' to_field_name='name'
) )
tenant = CSVModelChoiceField( tenant = CSVModelChoiceField(
@ -87,6 +88,7 @@ class TunnelTerminationImportForm(NetBoxModelImportForm):
outside_ip = CSVModelChoiceField( outside_ip = CSVModelChoiceField(
label=_('Outside IP'), label=_('Outside IP'),
queryset=IPAddress.objects.all(), queryset=IPAddress.objects.all(),
required=False,
to_field_name='name' to_field_name='name'
) )
@ -111,6 +113,14 @@ class TunnelTerminationImportForm(NetBoxModelImportForm):
**{f"virtual_machine__{self.fields['virtual_machine'].to_field_name}": data['virtual_machine']} **{f"virtual_machine__{self.fields['virtual_machine'].to_field_name}": data['virtual_machine']}
) )
def save(self, *args, **kwargs):
# Set interface assignment
if self.cleaned_data.get('interface'):
self.instance.interface = self.cleaned_data['interface']
return super().save(*args, **kwargs)
class IKEProposalImportForm(NetBoxModelImportForm): class IKEProposalImportForm(NetBoxModelImportForm):
authentication_method = CSVChoiceField( authentication_method = CSVChoiceField(
@ -121,7 +131,7 @@ class IKEProposalImportForm(NetBoxModelImportForm):
label=_('Encryption algorithm'), label=_('Encryption algorithm'),
choices=EncryptionAlgorithmChoices choices=EncryptionAlgorithmChoices
) )
authentication_algorithmn = CSVChoiceField( authentication_algorithm = CSVChoiceField(
label=_('Authentication algorithm'), label=_('Authentication algorithm'),
choices=AuthenticationAlgorithmChoices choices=AuthenticationAlgorithmChoices
) )
@ -133,7 +143,7 @@ class IKEProposalImportForm(NetBoxModelImportForm):
class Meta: class Meta:
model = IKEProposal model = IKEProposal
fields = ( fields = (
'name', 'description', 'authentication_method', 'encryption_algorithm', 'authentication_algorithmn', 'name', 'description', 'authentication_method', 'encryption_algorithm', 'authentication_algorithm',
'group', 'sa_lifetime', 'tags', 'group', 'sa_lifetime', 'tags',
) )
@ -147,7 +157,11 @@ class IKEPolicyImportForm(NetBoxModelImportForm):
label=_('Mode'), label=_('Mode'),
choices=IKEModeChoices choices=IKEModeChoices
) )
# TODO: M2M field for proposals proposals = CSVModelMultipleChoiceField(
queryset=IKEProposal.objects.all(),
to_field_name='name',
help_text=_('IKE proposal(s)'),
)
class Meta: class Meta:
model = IKEPolicy model = IKEPolicy
@ -161,7 +175,7 @@ class IPSecProposalImportForm(NetBoxModelImportForm):
label=_('Encryption algorithm'), label=_('Encryption algorithm'),
choices=EncryptionAlgorithmChoices choices=EncryptionAlgorithmChoices
) )
authentication_algorithmn = CSVChoiceField( authentication_algorithm = CSVChoiceField(
label=_('Authentication algorithm'), label=_('Authentication algorithm'),
choices=AuthenticationAlgorithmChoices choices=AuthenticationAlgorithmChoices
) )
@ -169,7 +183,7 @@ class IPSecProposalImportForm(NetBoxModelImportForm):
class Meta: class Meta:
model = IPSecProposal model = IPSecProposal
fields = ( fields = (
'name', 'description', 'encryption_algorithm', 'authentication_algorithmn', 'sa_lifetime_seconds', 'name', 'description', 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds',
'sa_lifetime_data', 'tags', 'sa_lifetime_data', 'tags',
) )
@ -179,7 +193,11 @@ class IPSecPolicyImportForm(NetBoxModelImportForm):
label=_('PFS group'), label=_('PFS group'),
choices=DHGroupChoices choices=DHGroupChoices
) )
# TODO: M2M field for proposals proposals = CSVModelMultipleChoiceField(
queryset=IPSecProposal.objects.all(),
to_field_name='name',
help_text=_('IPSec proposal(s)'),
)
class Meta: class Meta:
model = IPSecPolicy model = IPSecPolicy

View File

@ -6,6 +6,7 @@ from ipam.models import IPAddress
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField
from utilities.forms.utils import add_blank_choice
from utilities.forms.widgets import HTMXSelect from utilities.forms.widgets import HTMXSelect
from virtualization.models import VirtualMachine, VMInterface from virtualization.models import VirtualMachine, VMInterface
from vpn.choices import * from vpn.choices import *
@ -20,7 +21,6 @@ __all__ = (
'TunnelCreateForm', 'TunnelCreateForm',
'TunnelForm', 'TunnelForm',
'TunnelTerminationForm', 'TunnelTerminationForm',
'TunnelTerminationCreateForm',
) )
@ -49,21 +49,25 @@ class TunnelForm(TenancyForm, NetBoxModelForm):
class TunnelCreateForm(TunnelForm): class TunnelCreateForm(TunnelForm):
# First termination # First termination
termination1_role = forms.ChoiceField( termination1_role = forms.ChoiceField(
choices=TunnelTerminationRoleChoices, choices=add_blank_choice(TunnelTerminationRoleChoices),
required=False,
label=_('Role') label=_('Role')
) )
termination1_type = forms.ChoiceField( termination1_type = forms.ChoiceField(
choices=TunnelTerminationTypeChoices, choices=TunnelTerminationTypeChoices,
required=False,
widget=HTMXSelect(), widget=HTMXSelect(),
label=_('Type') label=_('Type')
) )
termination1_parent = DynamicModelChoiceField( termination1_parent = DynamicModelChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False,
selector=True, selector=True,
label=_('Device') label=_('Device')
) )
termination1_interface = DynamicModelChoiceField( termination1_interface = DynamicModelChoiceField(
queryset=Interface.objects.all(), queryset=Interface.objects.all(),
required=False,
label=_('Interface'), label=_('Interface'),
query_params={ query_params={
'device_id': '$termination1_parent', 'device_id': '$termination1_parent',
@ -80,7 +84,7 @@ class TunnelCreateForm(TunnelForm):
# Second termination # Second termination
termination2_role = forms.ChoiceField( termination2_role = forms.ChoiceField(
choices=TunnelTerminationRoleChoices, choices=add_blank_choice(TunnelTerminationRoleChoices),
required=False, required=False,
label=_('Role') label=_('Role')
) )
@ -155,34 +159,36 @@ class TunnelCreateForm(TunnelForm):
def clean(self): def clean(self):
super().clean() super().clean()
# Check that all required parameters have been set for the second termination (if any) # Validate attributes for each termination (if any)
termination2_required_parameters = ( for term in ('termination1', 'termination2'):
'termination2_role', 'termination2_type', 'termination2_parent', 'termination2_interface', required_parameters = (
) f'{term}_role', f'{term}_parent', f'{term}_interface',
termination2_parameters = ( )
*termination2_required_parameters, parameters = (
'termination2_outside_ip', *required_parameters,
) f'{term}_outside_ip',
if any([self.cleaned_data[param] for param in termination2_parameters]): )
for param in termination2_required_parameters: if any([self.cleaned_data[param] for param in parameters]):
for param in required_parameters:
if not self.cleaned_data[param]: if not self.cleaned_data[param]:
raise forms.ValidationError({ raise forms.ValidationError({
param: _("This parameter is required when defining a second termination.") param: _("This parameter is required when defining a termination.")
}) })
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
instance = super().save(*args, **kwargs) instance = super().save(*args, **kwargs)
# Create first termination # Create first termination
TunnelTermination.objects.create( if self.cleaned_data['termination1_interface']:
tunnel=instance, TunnelTermination.objects.create(
role=self.cleaned_data['termination1_role'], tunnel=instance,
interface=self.cleaned_data['termination1_interface'], role=self.cleaned_data['termination1_role'],
outside_ip=self.cleaned_data['termination1_outside_ip'], interface=self.cleaned_data['termination1_interface'],
) outside_ip=self.cleaned_data['termination1_outside_ip'],
)
# Create second termination, if defined # Create second termination, if defined
if self.cleaned_data['termination2_role']: if self.cleaned_data['termination2_interface']:
TunnelTermination.objects.create( TunnelTermination.objects.create(
tunnel=instance, tunnel=instance,
role=self.cleaned_data['termination2_role'], role=self.cleaned_data['termination2_role'],
@ -194,20 +200,6 @@ class TunnelCreateForm(TunnelForm):
class TunnelTerminationForm(NetBoxModelForm): class TunnelTerminationForm(NetBoxModelForm):
outside_ip = DynamicModelChoiceField(
queryset=IPAddress.objects.all(),
required=False,
label=_('Outside IP')
)
class Meta:
model = TunnelTermination
fields = [
'role', 'outside_ip', 'tags',
]
class TunnelTerminationCreateForm(NetBoxModelForm):
tunnel = DynamicModelChoiceField( tunnel = DynamicModelChoiceField(
queryset=Tunnel.objects.all() queryset=Tunnel.objects.all()
) )
@ -261,11 +253,15 @@ class TunnelTerminationCreateForm(NetBoxModelForm):
'virtual_machine_id': '$parent', 'virtual_machine_id': '$parent',
}) })
if self.instance.pk:
self.fields['parent'].initial = self.instance.interface.parent_object
self.fields['interface'].initial = self.instance.interface
def clean(self): def clean(self):
super().clean() super().clean()
# Assign the interface # Assign the interface
self.instance.interface = self.cleaned_data['interface'] self.instance.interface = self.cleaned_data.get('interface')
class IKEProposalForm(NetBoxModelForm): class IKEProposalForm(NetBoxModelForm):

View File

@ -119,7 +119,7 @@ class TunnelTermination(CustomFieldsMixin, CustomLinksMixin, TagsMixin, ChangeLo
return f'{self.tunnel}: Termination {self.pk}' return f'{self.tunnel}: Termination {self.pk}'
def get_absolute_url(self): def get_absolute_url(self):
return self.tunnel.get_absolute_url() return reverse('vpn:tunneltermination', args=[self.pk])
def get_role_color(self): def get_role_color(self):
return TunnelTerminationRoleChoices.colors.get(self.role) return TunnelTerminationRoleChoices.colors.get(self.role)
@ -128,7 +128,7 @@ class TunnelTermination(CustomFieldsMixin, CustomLinksMixin, TagsMixin, ChangeLo
super().clean() super().clean()
# Check that the selected Interface is not already attached to a Tunnel # Check that the selected Interface is not already attached to a Tunnel
if self.interface.tunnel_termination and self.interface.tunnel_termination.pk != self.pk: if getattr(self.interface, 'tunnel_termination', None) and self.interface.tunnel_termination.pk != self.pk:
raise ValidationError({ raise ValidationError({
'interface': _("Interface {name} is already attached to a tunnel ({tunnel}).").format( 'interface': _("Interface {name} is already attached to a tunnel ({tunnel}).").format(
name=self.interface.name, name=self.interface.name,

View File

@ -89,7 +89,7 @@ class TunnelTerminationTable(TenancyColumnsMixin, NetBoxTable):
'pk', 'id', 'tunnel', 'role', 'interface_parent', 'interface', 'ip_addresses', 'outside_ip', 'tags', 'pk', 'id', 'tunnel', 'role', 'interface_parent', 'interface', 'ip_addresses', 'outside_ip', 'tags',
'created', 'last_updated', 'created', 'last_updated',
) )
default_columns = ('pk', 'tunnel', 'role', 'interface_parent', 'interface', 'ip_addresses', 'outside_ip') default_columns = ('pk', 'id', 'tunnel', 'role', 'interface_parent', 'interface', 'ip_addresses', 'outside_ip')
class IKEProposalTable(NetBoxTable): class IKEProposalTable(NetBoxTable):

View File

@ -0,0 +1,509 @@
from django.contrib.contenttypes.models import ContentType
from dcim.choices import InterfaceTypeChoices
from dcim.models import Interface
from vpn.choices import *
from vpn.models import *
from utilities.testing import ViewTestCases, create_tags, create_test_device
class TunnelTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = Tunnel
@classmethod
def setUpTestData(cls):
tunnels = (
Tunnel(
name='Tunnel 1',
status=TunnelStatusChoices.STATUS_ACTIVE,
encapsulation=TunnelEncapsulationChoices.ENCAP_IP_IP
),
Tunnel(
name='Tunnel 2',
status=TunnelStatusChoices.STATUS_ACTIVE,
encapsulation=TunnelEncapsulationChoices.ENCAP_IP_IP
),
Tunnel(
name='Tunnel 3',
status=TunnelStatusChoices.STATUS_ACTIVE,
encapsulation=TunnelEncapsulationChoices.ENCAP_IP_IP
),
)
Tunnel.objects.bulk_create(tunnels)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Tunnel X',
'description': 'New tunnel',
'status': TunnelStatusChoices.STATUS_PLANNED,
'encapsulation': TunnelEncapsulationChoices.ENCAP_GRE,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,status,encapsulation",
"Tunnel 4,planned,gre",
"Tunnel 5,planned,gre",
"Tunnel 6,planned,gre",
)
cls.csv_update_data = (
"id,status,encapsulation",
f"{tunnels[0].pk},active,ip-ip",
f"{tunnels[1].pk},active,ip-ip",
f"{tunnels[2].pk},active,ip-ip",
)
cls.bulk_edit_data = {
'description': 'New description',
'status': TunnelStatusChoices.STATUS_DISABLED,
'encapsulation': TunnelEncapsulationChoices.ENCAP_GRE,
}
class TunnelTerminationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = TunnelTermination
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
interfaces = (
Interface(device=device, name='Interface 1', type=InterfaceTypeChoices.TYPE_VIRTUAL),
Interface(device=device, name='Interface 2', type=InterfaceTypeChoices.TYPE_VIRTUAL),
Interface(device=device, name='Interface 3', type=InterfaceTypeChoices.TYPE_VIRTUAL),
Interface(device=device, name='Interface 4', type=InterfaceTypeChoices.TYPE_VIRTUAL),
Interface(device=device, name='Interface 5', type=InterfaceTypeChoices.TYPE_VIRTUAL),
Interface(device=device, name='Interface 6', type=InterfaceTypeChoices.TYPE_VIRTUAL),
Interface(device=device, name='Interface 7', type=InterfaceTypeChoices.TYPE_VIRTUAL),
)
Interface.objects.bulk_create(interfaces)
tunnel = Tunnel.objects.create(
name='Tunnel 1',
status=TunnelStatusChoices.STATUS_ACTIVE,
encapsulation=TunnelEncapsulationChoices.ENCAP_IP_IP
)
tunnel_terminations = (
TunnelTermination(
tunnel=tunnel,
role=TunnelTerminationRoleChoices.ROLE_HUB,
interface=interfaces[0]
),
TunnelTermination(
tunnel=tunnel,
role=TunnelTerminationRoleChoices.ROLE_SPOKE,
interface=interfaces[1]
),
TunnelTermination(
tunnel=tunnel,
role=TunnelTerminationRoleChoices.ROLE_SPOKE,
interface=interfaces[2]
),
)
TunnelTermination.objects.bulk_create(tunnel_terminations)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'tunnel': tunnel.pk,
'role': TunnelTerminationRoleChoices.ROLE_PEER,
'type': TunnelTerminationTypeChoices.TYPE_DEVICE,
'parent': device.pk,
# TODO: Solve for GFK validation
'interface': interfaces[6].pk,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"tunnel,role,device,interface",
"Tunnel 1,peer,Device 1,Interface 4",
"Tunnel 1,peer,Device 1,Interface 5",
"Tunnel 1,peer,Device 1,Interface 6",
)
cls.csv_update_data = (
"id,role",
f"{tunnel_terminations[0].pk},peer",
f"{tunnel_terminations[1].pk},peer",
f"{tunnel_terminations[2].pk},peer",
)
cls.bulk_edit_data = {
'role': TunnelTerminationRoleChoices.ROLE_PEER,
}
class IKEProposalTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = IKEProposal
@classmethod
def setUpTestData(cls):
ike_proposals = (
IKEProposal(
name='IKE Proposal 1',
authentication_method=AuthenticationMethodChoices.PRESHARED_KEYS,
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
group=DHGroupChoices.GROUP_14
),
IKEProposal(
name='IKE Proposal 2',
authentication_method=AuthenticationMethodChoices.PRESHARED_KEYS,
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
group=DHGroupChoices.GROUP_14
),
IKEProposal(
name='IKE Proposal 3',
authentication_method=AuthenticationMethodChoices.PRESHARED_KEYS,
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
group=DHGroupChoices.GROUP_14
),
)
IKEProposal.objects.bulk_create(ike_proposals)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'IKE Proposal X',
'authentication_method': AuthenticationMethodChoices.CERTIFICATES,
'encryption_algorithm': EncryptionAlgorithmChoices.ENCRYPTION_AES192_CBC,
'authentication_algorithm': AuthenticationAlgorithmChoices.AUTH_HMAC_SHA256,
'group': DHGroupChoices.GROUP_19,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,authentication_method,encryption_algorithm,authentication_algorithm,group",
"IKE Proposal 4,preshared-keys,aes-128-cbc,hmac-sha1,14",
"IKE Proposal 5,preshared-keys,aes-128-cbc,hmac-sha1,14",
"IKE Proposal 6,preshared-keys,aes-128-cbc,hmac-sha1,14",
)
cls.csv_update_data = (
"id,description",
f"{ike_proposals[0].pk},New description",
f"{ike_proposals[1].pk},New description",
f"{ike_proposals[2].pk},New description",
)
cls.bulk_edit_data = {
'description': 'New description',
'authentication_method': AuthenticationMethodChoices.CERTIFICATES,
'encryption_algorithm': EncryptionAlgorithmChoices.ENCRYPTION_AES192_CBC,
'authentication_algorithm': AuthenticationAlgorithmChoices.AUTH_HMAC_SHA256,
'group': DHGroupChoices.GROUP_19
}
class IKEPolicyTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = IKEPolicy
@classmethod
def setUpTestData(cls):
ike_proposals = (
IKEProposal(
name='IKE Proposal 1',
authentication_method=AuthenticationMethodChoices.PRESHARED_KEYS,
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
group=DHGroupChoices.GROUP_14
),
IKEProposal(
name='IKE Proposal 2',
authentication_method=AuthenticationMethodChoices.PRESHARED_KEYS,
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
group=DHGroupChoices.GROUP_14
),
)
IKEProposal.objects.bulk_create(ike_proposals)
ike_policies = (
IKEPolicy(
name='IKE Policy 1',
version=IKEVersionChoices.VERSION_1,
mode=IKEModeChoices.MAIN,
),
IKEPolicy(
name='IKE Policy 2',
version=IKEVersionChoices.VERSION_1,
mode=IKEModeChoices.MAIN,
),
IKEPolicy(
name='IKE Policy 3',
version=IKEVersionChoices.VERSION_1,
mode=IKEModeChoices.MAIN,
),
)
IKEPolicy.objects.bulk_create(ike_policies)
for ike_policy in ike_policies:
ike_policy.proposals.set(ike_proposals)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'IKE Policy X',
'version': IKEVersionChoices.VERSION_2,
'mode': IKEModeChoices.AGGRESSIVE,
'proposals': [p.pk for p in ike_proposals],
'tags': [t.pk for t in tags],
}
ike_proposal_names = ','.join([p.name for p in ike_proposals])
cls.csv_data = (
"name,version,mode,proposals",
f"IKE Proposal 4,2,aggressive,\"{ike_proposal_names}\"",
f"IKE Proposal 5,2,aggressive,\"{ike_proposal_names}\"",
f"IKE Proposal 6,2,aggressive,\"{ike_proposal_names}\"",
)
cls.csv_update_data = (
"id,description",
f"{ike_policies[0].pk},New description",
f"{ike_policies[1].pk},New description",
f"{ike_policies[2].pk},New description",
)
cls.bulk_edit_data = {
'description': 'New description',
'version': IKEVersionChoices.VERSION_2,
'mode': IKEModeChoices.AGGRESSIVE,
}
class IPSecProposalTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = IPSecProposal
@classmethod
def setUpTestData(cls):
ipsec_proposals = (
IPSecProposal(
name='IPSec Proposal 1',
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
),
IPSecProposal(
name='IPSec Proposal 2',
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
),
IPSecProposal(
name='IPSec Proposal 3',
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
),
)
IPSecProposal.objects.bulk_create(ipsec_proposals)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'IPSec Proposal X',
'encryption_algorithm': EncryptionAlgorithmChoices.ENCRYPTION_AES192_CBC,
'authentication_algorithm': AuthenticationAlgorithmChoices.AUTH_HMAC_SHA256,
'sa_lifetime_seconds': 3600,
'sa_lifetime_data': 1000000,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,encryption_algorithm,authentication_algorithm,sa_lifetime_seconds,sa_lifetime_data",
"IKE Proposal 4,aes-128-cbc,hmac-sha1,3600,1000000",
"IKE Proposal 5,aes-128-cbc,hmac-sha1,3600,1000000",
"IKE Proposal 6,aes-128-cbc,hmac-sha1,3600,1000000",
)
cls.csv_update_data = (
"id,description",
f"{ipsec_proposals[0].pk},New description",
f"{ipsec_proposals[1].pk},New description",
f"{ipsec_proposals[2].pk},New description",
)
cls.bulk_edit_data = {
'description': 'New description',
'encryption_algorithm': EncryptionAlgorithmChoices.ENCRYPTION_AES192_CBC,
'authentication_algorithm': AuthenticationAlgorithmChoices.AUTH_HMAC_SHA256,
'sa_lifetime_seconds': 3600,
'sa_lifetime_data': 1000000,
}
class IPSecPolicyTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = IPSecPolicy
@classmethod
def setUpTestData(cls):
ipsec_proposals = (
IPSecProposal(
name='IPSec Policy 1',
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1
),
IPSecProposal(
name='IPSec Proposal 2',
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1
),
)
IPSecProposal.objects.bulk_create(ipsec_proposals)
ipsec_policies = (
IPSecPolicy(
name='IPSec Policy 1',
pfs_group=DHGroupChoices.GROUP_14
),
IPSecPolicy(
name='IPSec Policy 2',
pfs_group=DHGroupChoices.GROUP_14
),
IPSecPolicy(
name='IPSec Policy 3',
pfs_group=DHGroupChoices.GROUP_14
),
)
IPSecPolicy.objects.bulk_create(ipsec_policies)
for ipsec_policy in ipsec_policies:
ipsec_policy.proposals.set(ipsec_proposals)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'IPSec Policy X',
'pfs_group': DHGroupChoices.GROUP_5,
'proposals': [p.pk for p in ipsec_proposals],
'tags': [t.pk for t in tags],
}
ipsec_proposal_names = ','.join([p.name for p in ipsec_proposals])
cls.csv_data = (
"name,pfs_group,proposals",
f"IKE Proposal 4,19,\"{ipsec_proposal_names}\"",
f"IKE Proposal 5,19,\"{ipsec_proposal_names}\"",
f"IKE Proposal 6,19,\"{ipsec_proposal_names}\"",
)
cls.csv_update_data = (
"id,description",
f"{ipsec_policies[0].pk},New description",
f"{ipsec_policies[1].pk},New description",
f"{ipsec_policies[2].pk},New description",
)
cls.bulk_edit_data = {
'description': 'New description',
'pfs_group': DHGroupChoices.GROUP_5,
}
class IPSecProfileTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = IPSecProfile
@classmethod
def setUpTestData(cls):
ike_proposal = IKEProposal.objects.create(
name='IKE Proposal 1',
authentication_method=AuthenticationMethodChoices.PRESHARED_KEYS,
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1,
group=DHGroupChoices.GROUP_14
)
ipsec_proposal = IPSecProposal.objects.create(
name='IPSec Proposal 1',
encryption_algorithm=EncryptionAlgorithmChoices.ENCRYPTION_AES128_CBC,
authentication_algorithm=AuthenticationAlgorithmChoices.AUTH_HMAC_SHA1
)
ike_policies = (
IKEPolicy(
name='IKE Policy 1',
version=IKEVersionChoices.VERSION_1,
mode=IKEModeChoices.MAIN,
),
IKEPolicy(
name='IKE Policy 2',
version=IKEVersionChoices.VERSION_1,
mode=IKEModeChoices.MAIN,
),
)
IKEPolicy.objects.bulk_create(ike_policies)
for ike_policy in ike_policies:
ike_policy.proposals.add(ike_proposal)
ipsec_policies = (
IPSecPolicy(
name='IPSec Policy 1',
pfs_group=DHGroupChoices.GROUP_14
),
IPSecPolicy(
name='IPSec Policy 2',
pfs_group=DHGroupChoices.GROUP_14
),
)
IPSecPolicy.objects.bulk_create(ipsec_policies)
for ipsec_policy in ipsec_policies:
ipsec_policy.proposals.add(ipsec_proposal)
ipsec_profiles = (
IPSecProfile(
name='IPSec Profile 1',
mode=IPSecModeChoices.ESP,
ike_policy=ike_policies[0],
ipsec_policy=ipsec_policies[0]
),
IPSecProfile(
name='IPSec Profile 2',
mode=IPSecModeChoices.ESP,
ike_policy=ike_policies[0],
ipsec_policy=ipsec_policies[0]
),
IPSecProfile(
name='IPSec Profile 3',
mode=IPSecModeChoices.ESP,
ike_policy=ike_policies[0],
ipsec_policy=ipsec_policies[0]
),
)
IPSecProfile.objects.bulk_create(ipsec_profiles)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'IPSec Profile X',
'mode': IPSecModeChoices.AH,
'ike_policy': ike_policies[1].pk,
'ipsec_policy': ipsec_policies[1].pk,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,mode,ike_policy,ipsec_policy",
f"IKE Proposal 4,ah,IKE Policy 2,IPSec Policy 2",
f"IKE Proposal 5,ah,IKE Policy 2,IPSec Policy 2",
f"IKE Proposal 6,ah,IKE Policy 2,IPSec Policy 2",
)
cls.csv_update_data = (
"id,description",
f"{ipsec_profiles[0].pk},New description",
f"{ipsec_profiles[1].pk},New description",
f"{ipsec_profiles[2].pk},New description",
)
cls.bulk_edit_data = {
'description': 'New description',
'mode': IPSecModeChoices.AH,
'ike_policy': ike_policies[1].pk,
'ipsec_policy': ipsec_policies[1].pk,
}

View File

@ -75,19 +75,16 @@ class TunnelTerminationListView(generic.ObjectListView):
table = tables.TunnelTerminationTable table = tables.TunnelTerminationTable
@register_model_view(TunnelTermination)
class TunnelTerminationView(generic.ObjectView):
queryset = TunnelTermination.objects.all()
@register_model_view(TunnelTermination, 'edit') @register_model_view(TunnelTermination, 'edit')
class TunnelTerminationEditView(generic.ObjectEditView): class TunnelTerminationEditView(generic.ObjectEditView):
queryset = TunnelTermination.objects.all() queryset = TunnelTermination.objects.all()
form = forms.TunnelTerminationForm form = forms.TunnelTerminationForm
def dispatch(self, request, *args, **kwargs):
# If creating a new Tunnel, use the creation form
if 'pk' not in kwargs:
self.form = forms.TunnelTerminationCreateForm
return super().dispatch(request, *args, **kwargs)
@register_model_view(TunnelTermination, 'delete') @register_model_view(TunnelTermination, 'delete')
class TunnelTerminationDeleteView(generic.ObjectDeleteView): class TunnelTerminationDeleteView(generic.ObjectDeleteView):