瀏覽代碼

Fixes #14499: Relax requirements for encryption/auth algorithms on IKE & IPSec proposals

Jeremy Stretch 2 年之前
父節點
當前提交
b794bd6fb8

+ 1 - 1
docs/models/vpn/ikeproposal.md

@@ -28,7 +28,7 @@ The protocol employed for data encryption. Options include DES, 3DES, and variou
 
 
 ### Authentication Algorithm
 ### Authentication Algorithm
 
 
-The mechanism employed to ensure data integrity. Options include MD5 and SHA HMAC implementations.
+The mechanism employed to ensure data integrity. Options include MD5 and SHA HMAC implementations. Specifying an authentication algorithm is optional, as some encryption algorithms (e.g. AES-GCM) provide authentication natively.
 
 
 ### Group
 ### Group
 
 

+ 6 - 0
docs/models/vpn/ipsecproposal.md

@@ -12,10 +12,16 @@ The unique user-assigned name for the proposal.
 
 
 The protocol employed for data encryption. Options include DES, 3DES, and various flavors of AES.
 The protocol employed for data encryption. Options include DES, 3DES, and various flavors of AES.
 
 
+!!! note
+    If an encryption algorithm is not specified, an authentication algorithm must be specified.
+
 ### Authentication Algorithm
 ### Authentication Algorithm
 
 
 The mechanism employed to ensure data integrity. Options include MD5 and SHA HMAC implementations.
 The mechanism employed to ensure data integrity. Options include MD5 and SHA HMAC implementations.
 
 
+!!! note
+    If an authentication algorithm is not specified, an encryption algorithm must be specified.
+
 ### SA Lifetime (Seconds)
 ### SA Lifetime (Seconds)
 
 
 The maximum amount of time for which the security association (SA) may be active, in seconds.
 The maximum amount of time for which the security association (SA) may be active, in seconds.

+ 3 - 3
netbox/vpn/migrations/0001_initial.py

@@ -29,7 +29,7 @@ class Migration(migrations.Migration):
                 ('name', models.CharField(max_length=100, unique=True)),
                 ('name', models.CharField(max_length=100, unique=True)),
                 ('authentication_method', models.CharField()),
                 ('authentication_method', models.CharField()),
                 ('encryption_algorithm', models.CharField()),
                 ('encryption_algorithm', models.CharField()),
-                ('authentication_algorithm', models.CharField()),
+                ('authentication_algorithm', models.CharField(blank=True)),
                 ('group', models.PositiveSmallIntegerField()),
                 ('group', models.PositiveSmallIntegerField()),
                 ('sa_lifetime', models.PositiveIntegerField(blank=True, null=True)),
                 ('sa_lifetime', models.PositiveIntegerField(blank=True, null=True)),
                 ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
                 ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
@@ -82,8 +82,8 @@ class Migration(migrations.Migration):
                 ('description', models.CharField(blank=True, max_length=200)),
                 ('description', models.CharField(blank=True, max_length=200)),
                 ('comments', models.TextField(blank=True)),
                 ('comments', models.TextField(blank=True)),
                 ('name', models.CharField(max_length=100, unique=True)),
                 ('name', models.CharField(max_length=100, unique=True)),
-                ('encryption_algorithm', models.CharField()),
-                ('authentication_algorithm', models.CharField()),
+                ('encryption_algorithm', models.CharField(blank=True)),
+                ('authentication_algorithm', models.CharField(blank=True)),
                 ('sa_lifetime_seconds', models.PositiveIntegerField(blank=True, null=True)),
                 ('sa_lifetime_seconds', models.PositiveIntegerField(blank=True, null=True)),
                 ('sa_lifetime_data', models.PositiveIntegerField(blank=True, null=True)),
                 ('sa_lifetime_data', models.PositiveIntegerField(blank=True, null=True)),
                 ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
                 ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),

+ 14 - 3
netbox/vpn/models/crypto.py

@@ -1,3 +1,4 @@
+from django.core.exceptions import ValidationError
 from django.db import models
 from django.db import models
 from django.urls import reverse
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import gettext_lazy as _
@@ -34,7 +35,8 @@ class IKEProposal(PrimaryModel):
     )
     )
     authentication_algorithm = models.CharField(
     authentication_algorithm = models.CharField(
         verbose_name=_('authentication algorithm'),
         verbose_name=_('authentication algorithm'),
-        choices=AuthenticationAlgorithmChoices
+        choices=AuthenticationAlgorithmChoices,
+        blank=True
     )
     )
     group = models.PositiveSmallIntegerField(
     group = models.PositiveSmallIntegerField(
         verbose_name=_('group'),
         verbose_name=_('group'),
@@ -120,11 +122,13 @@ class IPSecProposal(PrimaryModel):
     )
     )
     encryption_algorithm = models.CharField(
     encryption_algorithm = models.CharField(
         verbose_name=_('encryption'),
         verbose_name=_('encryption'),
-        choices=EncryptionAlgorithmChoices
+        choices=EncryptionAlgorithmChoices,
+        blank=True
     )
     )
     authentication_algorithm = models.CharField(
     authentication_algorithm = models.CharField(
         verbose_name=_('authentication'),
         verbose_name=_('authentication'),
-        choices=AuthenticationAlgorithmChoices
+        choices=AuthenticationAlgorithmChoices,
+        blank=True
     )
     )
     sa_lifetime_seconds = models.PositiveIntegerField(
     sa_lifetime_seconds = models.PositiveIntegerField(
         verbose_name=_('SA lifetime (seconds)'),
         verbose_name=_('SA lifetime (seconds)'),
@@ -154,6 +158,13 @@ class IPSecProposal(PrimaryModel):
     def get_absolute_url(self):
     def get_absolute_url(self):
         return reverse('vpn:ipsecproposal', args=[self.pk])
         return reverse('vpn:ipsecproposal', args=[self.pk])
 
 
+    def clean(self):
+        super().clean()
+
+        # Encryption and/or authentication algorithm must be defined
+        if not self.encryption_algorithm and not self.authentication_algorithm:
+            raise ValidationError(_("Encryption and/or authentication algorithm must be defined"))
+
 
 
 class IPSecPolicy(PrimaryModel):
 class IPSecPolicy(PrimaryModel):
     name = models.CharField(
     name = models.CharField(