diff --git a/netbox/templates/vpn/ipsecprofile.html b/netbox/templates/vpn/ipsecprofile.html index d2247bdd0..aa65393ae 100644 --- a/netbox/templates/vpn/ipsecprofile.html +++ b/netbox/templates/vpn/ipsecprofile.html @@ -14,77 +14,31 @@ {% trans "Name" %} {{ object.name }} - - {% trans "Protocol" %} - {{ object.get_protocol_display }} - - - {% trans "IKE Version" %} - {{ object.get_ike_version_display }} - {% trans "Description" %} {{ object.description|placeholder }} + + {% trans "Mode" %} + {{ object.get_mode_display }} + + + {% trans "IKE Policy" %} + {{ object.ike_policy|linkify }} + + + {% trans "IPSec Policy" %} + {{ object.ipsec_policy|linkify }} + - {% include 'inc/panels/custom_fields.html' %} {% include 'inc/panels/tags.html' %} {% include 'inc/panels/comments.html' %} {% plugin_left_page object %}
-
-
{% trans "Phase 1 Parameters" %}
-
- - - - - - - - - - - - - - - - - -
{% trans "Encryption" %}{{ object.get_phase1_encryption_display }}
{% trans "Authentication" %}{{ object.get_phase1_authentication_display }}
{% trans "DH Group" %}{{ object.get_phase1_group_display }}
{% trans "SA Lifetime" %}{{ object.phase1_sa_lifetime|placeholder }}
-
-
-
-
{% trans "Phase 2 Parameters" %}
-
- - - - - - - - - - - - - - - - - - - - - -
{% trans "Encryption" %}{{ object.get_phase2_encryption_display }}
{% trans "Authentication" %}{{ object.get_phase2_authentication_display }}
{% trans "DH Group" %}{{ object.get_phase2_group_display }}
{% trans "SA Lifetime (Seconds)" %}{{ object.phase2_sa_lifetime|placeholder }}
{% trans "SA Lifetime (KB)" %}{{ object.phase2_sa_lifetime_data|placeholder }}
-
-
+ {% include 'inc/panels/custom_fields.html' %} {% plugin_right_page object %}
diff --git a/netbox/vpn/api/nested_serializers.py b/netbox/vpn/api/nested_serializers.py index 9e2dee8ba..c9c92d308 100644 --- a/netbox/vpn/api/nested_serializers.py +++ b/netbox/vpn/api/nested_serializers.py @@ -50,7 +50,7 @@ class NestedIKEPolicySerializer(WritableNestedSerializer): ) class Meta: - model = models.IKEProposal + model = models.IKEPolicy fields = ('id', 'url', 'display', 'name') @@ -70,7 +70,7 @@ class NestedIPSecPolicySerializer(WritableNestedSerializer): ) class Meta: - model = models.IPSecProposal + model = models.IPSecPolicy fields = ('id', 'url', 'display', 'name') diff --git a/netbox/vpn/api/serializers.py b/netbox/vpn/api/serializers.py index 0ebe28dba..0117aa70f 100644 --- a/netbox/vpn/api/serializers.py +++ b/netbox/vpn/api/serializers.py @@ -118,12 +118,6 @@ class IKEPolicySerializer(NetBoxModelSerializer): mode = ChoiceField( choices=IKEModeChoices ) - authentication_algorithm = ChoiceField( - choices=AuthenticationAlgorithmChoices - ) - group = ChoiceField( - choices=DHGroupChoices - ) proposals = SerializedPKRelatedField( queryset=IKEProposal.objects.all(), serializer=NestedIKEProposalSerializer, @@ -149,9 +143,6 @@ class IPSecProposalSerializer(NetBoxModelSerializer): authentication_algorithm = ChoiceField( choices=AuthenticationAlgorithmChoices ) - group = ChoiceField( - choices=DHGroupChoices - ) class Meta: model = IPSecProposal @@ -187,36 +178,15 @@ class IPSecProfileSerializer(NetBoxModelSerializer): url = serializers.HyperlinkedIdentityField( view_name='vpn-api:ipsecprofile-detail' ) - protocol = ChoiceField( + mode = ChoiceField( choices=IPSecModeChoices ) - ike_version = ChoiceField( - choices=IKEVersionChoices - ) - phase1_encryption = ChoiceField( - choices=EncryptionAlgorithmChoices - ) - phase1_authentication = ChoiceField( - choices=AuthenticationAlgorithmChoices - ) - phase1_group = ChoiceField( - choices=DHGroupChoices - ) - phase2_encryption = ChoiceField( - choices=EncryptionAlgorithmChoices - ) - phase2_authentication = ChoiceField( - choices=AuthenticationAlgorithmChoices - ) - phase2_group = ChoiceField( - choices=DHGroupChoices - ) + ike_policy = NestedIKEPolicySerializer() + ipsec_policy = NestedIPSecPolicySerializer() class Meta: model = IPSecProfile fields = ( - 'id', 'url', 'display', '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', 'comments', 'tags', 'custom_fields', 'created', - 'last_updated', + 'id', 'url', 'display', 'name', 'description', 'mode', 'ike_policy', 'ipsec_policy', 'comments', 'tags', + 'custom_fields', 'created', 'last_updated', ) diff --git a/netbox/vpn/api/views.py b/netbox/vpn/api/views.py index 960bcb1b4..c0ccab7ab 100644 --- a/netbox/vpn/api/views.py +++ b/netbox/vpn/api/views.py @@ -63,7 +63,7 @@ class IPSecProposalViewSet(NetBoxModelViewSet): class IPSecPolicyViewSet(NetBoxModelViewSet): - queryset = IKEPolicy.objects.all() + queryset = IPSecPolicy.objects.all() serializer_class = serializers.IPSecPolicySerializer filterset_class = filtersets.IPSecPolicyFilterSet diff --git a/netbox/vpn/forms/bulk_edit.py b/netbox/vpn/forms/bulk_edit.py index d645ca02b..9a6b87c31 100644 --- a/netbox/vpn/forms/bulk_edit.py +++ b/netbox/vpn/forms/bulk_edit.py @@ -97,18 +97,25 @@ class IKEProposalBulkEditForm(NetBoxModelBulkEditForm): required=False ) sa_lifetime = forms.IntegerField( + label=_('SA lifetime'), required=False ) + description = forms.CharField( + label=_('Description'), + max_length=200, + required=False + ) + comments = CommentField() model = IKEProposal fieldsets = ( - (None, ('name', 'description')), - (_('Parameters'), ( + (None, ( 'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group', 'sa_lifetime', + 'description', )), ) nullable_fields = ( - 'description', 'sa_lifetime', 'comments', + 'sa_lifetime', 'description', 'comments', ) @@ -131,16 +138,21 @@ class IKEPolicyBulkEditForm(NetBoxModelBulkEditForm): label=_('Certificate'), required=False ) + description = forms.CharField( + label=_('Description'), + max_length=200, + required=False + ) + comments = CommentField() model = IKEPolicy fieldsets = ( - (None, ('name', 'description')), - (_('Parameters'), ( - 'version', 'mode', 'preshared_key', 'certificate', + (None, ( + 'version', 'mode', 'preshared_key', 'certificate', 'description', )), ) nullable_fields = ( - 'description', 'preshared_key', 'certificate', 'comments', + 'preshared_key', 'certificate', 'description', 'comments', ) @@ -156,21 +168,29 @@ class IPSecProposalBulkEditForm(NetBoxModelBulkEditForm): required=False ) sa_lifetime_seconds = forms.IntegerField( + label=_('SA lifetime (seconds)'), required=False ) sa_lifetime_data = forms.IntegerField( + label=_('SA lifetime (KB)'), required=False ) + description = forms.CharField( + label=_('Description'), + max_length=200, + required=False + ) + comments = CommentField() model = IPSecProposal fieldsets = ( - (None, ('name', 'description')), - (_('Parameters'), ( + (None, ( 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds', 'sa_lifetime_data', + 'description', )), ) nullable_fields = ( - 'description', 'sa_lifetime_seconds', 'sa_lifetime_data', 'comments', + 'sa_lifetime_seconds', 'sa_lifetime_data', 'description', 'comments', ) @@ -180,20 +200,38 @@ class IPSecPolicyBulkEditForm(NetBoxModelBulkEditForm): choices=add_blank_choice(DHGroupChoices), required=False ) + description = forms.CharField( + label=_('Description'), + max_length=200, + required=False + ) + comments = CommentField() model = IPSecPolicy fieldsets = ( - (None, ('name', 'description')), - (_('Parameters'), ( - 'pfs_group', - )), + (None, ('pfs_group', 'description',)), ) nullable_fields = ( - 'description', 'pfs_group', 'comments', + 'pfs_group', 'description', 'comments', ) class IPSecProfileBulkEditForm(NetBoxModelBulkEditForm): + mode = forms.ChoiceField( + label=_('Mode'), + choices=add_blank_choice(IPSecModeChoices), + required=False + ) + ike_policy = DynamicModelChoiceField( + label=_('IKE policy'), + queryset=IKEPolicy.objects.all(), + required=False + ) + ipsec_policy = DynamicModelChoiceField( + label=_('IPSec policy'), + queryset=IPSecPolicy.objects.all(), + required=False + ) description = forms.CharField( label=_('Description'), max_length=200, @@ -204,7 +242,7 @@ class IPSecProfileBulkEditForm(NetBoxModelBulkEditForm): model = IPSecProfile fieldsets = ( (_('Profile'), ( - 'protocol', 'ike_version', 'description', + 'mode', 'ike_policy', 'ipsec_policy', 'description', )), ) nullable_fields = ( diff --git a/netbox/vpn/forms/bulk_import.py b/netbox/vpn/forms/bulk_import.py index 1b19af25f..d961b156c 100644 --- a/netbox/vpn/forms/bulk_import.py +++ b/netbox/vpn/forms/bulk_import.py @@ -157,10 +157,6 @@ class IKEPolicyImportForm(NetBoxModelImportForm): class IPSecProposalImportForm(NetBoxModelImportForm): - authentication_method = CSVChoiceField( - label=_('Authentication method'), - choices=AuthenticationMethodChoices - ) encryption_algorithm = CSVChoiceField( label=_('Encryption algorithm'), choices=EncryptionAlgorithmChoices @@ -169,10 +165,6 @@ class IPSecProposalImportForm(NetBoxModelImportForm): label=_('Authentication algorithm'), choices=AuthenticationAlgorithmChoices ) - group = CSVChoiceField( - label=_('Group'), - choices=DHGroupChoices - ) class Meta: model = IPSecProposal @@ -216,5 +208,5 @@ class IPSecProfileImportForm(NetBoxModelImportForm): class Meta: model = IPSecProfile fields = ( - 'name', 'ike_policy', 'ipsec_policy', 'description', 'comments', 'tags', + 'name', 'mode', 'ike_policy', 'ipsec_policy', 'description', 'comments', 'tags', ) diff --git a/netbox/vpn/forms/filtersets.py b/netbox/vpn/forms/filtersets.py index 98a626857..ec146919a 100644 --- a/netbox/vpn/forms/filtersets.py +++ b/netbox/vpn/forms/filtersets.py @@ -143,7 +143,7 @@ class IPSecPolicyFilterForm(NetBoxModelFilterSetForm): model = IPSecPolicy fieldsets = ( (None, ('q', 'filter_id', 'tag')), - (_('Parameters'), ('proposal', 'pfs_group')), + (_('Parameters'), ('proposal_id', 'pfs_group')), ) proposal_id = DynamicModelMultipleChoiceField( queryset=IKEProposal.objects.all(), @@ -162,14 +162,7 @@ class IPSecProfileFilterForm(NetBoxModelFilterSetForm): model = IPSecProfile fieldsets = ( (None, ('q', 'filter_id', 'tag')), - (_('Profile'), ('protocol', 'ike_version')), - (_('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', - )), + (_('Profile'), ('mode', 'ike_policy_id', 'ipsec_policy_id')), ) mode = forms.MultipleChoiceField( label=_('Mode'), diff --git a/netbox/vpn/forms/model_forms.py b/netbox/vpn/forms/model_forms.py index 6f289d26e..49b9dab24 100644 --- a/netbox/vpn/forms/model_forms.py +++ b/netbox/vpn/forms/model_forms.py @@ -287,7 +287,8 @@ class IKEProposalForm(NetBoxModelForm): class IKEPolicyForm(NetBoxModelForm): proposals = DynamicModelMultipleChoiceField( - queryset=IKEProposal.objects.all() + queryset=IKEProposal.objects.all(), + label=_('Proposals') ) fieldsets = ( @@ -322,7 +323,8 @@ class IPSecProposalForm(NetBoxModelForm): class IPSecPolicyForm(NetBoxModelForm): proposals = DynamicModelMultipleChoiceField( - queryset=IPSecProposal.objects.all() + queryset=IPSecProposal.objects.all(), + label=_('Proposals') ) fieldsets = ( @@ -338,17 +340,23 @@ class IPSecPolicyForm(NetBoxModelForm): class IPSecProfileForm(NetBoxModelForm): + ike_policy = DynamicModelChoiceField( + queryset=IKEPolicy.objects.all(), + label=_('IKE policy') + ) + ipsec_policy = DynamicModelChoiceField( + queryset=IPSecPolicy.objects.all(), + label=_('IPSec policy') + ) comments = CommentField() fieldsets = ( - (_('Profile'), ( - 'name', 'mode', 'description', 'tags', - )), - (_('Policies'), ('ipsec_policy', 'description', 'tags')), + (_('Profile'), ('name', 'description', 'tags')), + (_('Parameters'), ('mode', 'ike_policy', 'ipsec_policy')), ) class Meta: model = IPSecProfile fields = [ - 'name', 'description', 'mode', 'ipsec_policy', 'description', 'comments', 'tags', + 'name', 'description', 'mode', 'ike_policy', 'ipsec_policy', 'description', 'comments', 'tags', ] diff --git a/netbox/vpn/graphql/schema.py b/netbox/vpn/graphql/schema.py index 0ec4cd207..64e680882 100644 --- a/netbox/vpn/graphql/schema.py +++ b/netbox/vpn/graphql/schema.py @@ -7,12 +7,37 @@ from .types import * class VPNQuery(graphene.ObjectType): + + ike_policy = ObjectField(IKEPolicyType) + ike_policy_list = ObjectListField(IKEPolicyType) + + def resolve_ike_policy_list(root, info, **kwargs): + return gql_query_optimizer(models.IKEPolicy.objects.all(), info) + + ike_proposal = ObjectField(IKEProposalType) + ike_proposal_list = ObjectListField(IKEProposalType) + + def resolve_ike_proposal_list(root, info, **kwargs): + return gql_query_optimizer(models.IKEProposal.objects.all(), info) + + ipsec_policy = ObjectField(IPSecPolicyType) + ipsec_policy_list = ObjectListField(IPSecPolicyType) + + def resolve_ipsec_policy_list(root, info, **kwargs): + return gql_query_optimizer(models.IPSecPolicy.objects.all(), info) + ipsec_profile = ObjectField(IPSecProfileType) ipsec_profile_list = ObjectListField(IPSecProfileType) def resolve_ipsec_profile_list(root, info, **kwargs): return gql_query_optimizer(models.IPSecProfile.objects.all(), info) + ipsec_proposal = ObjectField(IPSecProposalType) + ipsec_proposal_list = ObjectListField(IPSecProposalType) + + def resolve_ipsec_proposal_list(root, info, **kwargs): + return gql_query_optimizer(models.IPSecProposal.objects.all(), info) + tunnel = ObjectField(TunnelType) tunnel_list = ObjectListField(TunnelType) diff --git a/netbox/vpn/graphql/types.py b/netbox/vpn/graphql/types.py index d6b04ad2f..f46e8b697 100644 --- a/netbox/vpn/graphql/types.py +++ b/netbox/vpn/graphql/types.py @@ -3,7 +3,11 @@ from netbox.graphql.types import ObjectType, OrganizationalObjectType, NetBoxObj from vpn import filtersets, models __all__ = ( + 'IKEPolicyType', + 'IKEProposalType', + 'IPSecPolicyType', 'IPSecProfileType', + 'IPSecProposalType', 'TunnelTerminationType', 'TunnelType', ) @@ -25,6 +29,38 @@ class TunnelType(NetBoxObjectType): filterset_class = filtersets.TunnelFilterSet +class IKEProposalType(OrganizationalObjectType): + + class Meta: + model = models.IKEProposal + fields = '__all__' + filterset_class = filtersets.IKEProposalFilterSet + + +class IKEPolicyType(OrganizationalObjectType): + + class Meta: + model = models.IKEPolicy + fields = '__all__' + filterset_class = filtersets.IKEPolicyFilterSet + + +class IPSecProposalType(OrganizationalObjectType): + + class Meta: + model = models.IPSecProposal + fields = '__all__' + filterset_class = filtersets.IPSecProposalFilterSet + + +class IPSecPolicyType(OrganizationalObjectType): + + class Meta: + model = models.IPSecPolicy + fields = '__all__' + filterset_class = filtersets.IPSecPolicyFilterSet + + class IPSecProfileType(OrganizationalObjectType): class Meta: diff --git a/netbox/vpn/models/crypto.py b/netbox/vpn/models/crypto.py index dacd40f81..84a010a3e 100644 --- a/netbox/vpn/models/crypto.py +++ b/netbox/vpn/models/crypto.py @@ -53,6 +53,10 @@ class IKEProposal(NetBoxModel): help_text=_('Security association lifetime (in seconds)') ) + clone_fields = ( + 'authentication_method', 'encryption_algorithm', 'authentication_algorithm', 'group', 'sa_lifetime', + ) + class Meta: ordering = ('name',) verbose_name = _('IKE proposal') @@ -99,6 +103,13 @@ class IKEPolicy(NetBoxModel): blank=True ) + clone_fields = ( + 'version', 'mode', 'proposals', + ) + prerequisite_models = ( + 'vpn.IKEProposal', + ) + class Meta: ordering = ('name',) verbose_name = _('IKE policy') @@ -108,7 +119,7 @@ class IKEPolicy(NetBoxModel): return self.name def get_absolute_url(self): - return reverse('vpn:ikeprofile', args=[self.pk]) + return reverse('vpn:ikepolicy', args=[self.pk]) # @@ -147,6 +158,10 @@ class IPSecProposal(NetBoxModel): help_text=_('Security association lifetime (in kilobytes)') ) + clone_fields = ( + 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds', 'sa_lifetime_data', + ) + class Meta: ordering = ('name',) verbose_name = _('IPSec proposal') @@ -183,6 +198,13 @@ class IPSecPolicy(NetBoxModel): help_text=_('Diffie-Hellman group for Perfect Forward Secrecy') ) + clone_fields = ( + 'proposals', 'pfs_group', + ) + prerequisite_models = ( + 'vpn.IPSecProposal', + ) + class Meta: ordering = ('name',) verbose_name = _('IPSec policy') @@ -219,6 +241,10 @@ class IPSecProfile(PrimaryModel): clone_fields = ( 'mode', 'ike_policy', 'ipsec_policy', ) + prerequisite_models = ( + 'vpn.IKEPolicy', + 'vpn.IPSecPolicy', + ) class Meta: ordering = ('name',) diff --git a/netbox/vpn/tables.py b/netbox/vpn/tables.py index 3a358a972..ab1642969 100644 --- a/netbox/vpn/tables.py +++ b/netbox/vpn/tables.py @@ -97,16 +97,16 @@ class IKEProposalTable(NetBoxTable): verbose_name=_('Name'), linkify=True ) - authentication_method = columns.ChoiceFieldColumn( + authentication_method = tables.Column( verbose_name=_('Authentication Method') ) - encryption_algorithm = columns.ChoiceFieldColumn( + encryption_algorithm = tables.Column( verbose_name=_('Encryption Algorithm') ) - authentication_algorithm = columns.ChoiceFieldColumn( + authentication_algorithm = tables.Column( verbose_name=_('Authentication Algorithm') ) - group = columns.ChoiceFieldColumn( + group = tables.Column( verbose_name=_('Group') ) sa_lifetime = tables.Column( @@ -133,10 +133,10 @@ class IKEPolicyTable(NetBoxTable): verbose_name=_('Name'), linkify=True ) - version = columns.ChoiceFieldColumn( + version = tables.Column( verbose_name=_('Version') ) - mode = columns.ChoiceFieldColumn( + mode = tables.Column( verbose_name=_('Mode') ) proposals = tables.ManyToManyColumn( @@ -169,10 +169,10 @@ class IPSecProposalTable(NetBoxTable): verbose_name=_('Name'), linkify=True ) - encryption_algorithm = columns.ChoiceFieldColumn( + encryption_algorithm = tables.Column( verbose_name=_('Encryption Algorithm') ) - authentication_algorithm = columns.ChoiceFieldColumn( + authentication_algorithm = tables.Column( verbose_name=_('Authentication Algorithm') ) sa_lifetime_seconds = tables.Column( @@ -206,7 +206,7 @@ class IPSecPolicyTable(NetBoxTable): linkify_item=True, verbose_name=_('Proposals') ) - pfs_group = columns.ChoiceFieldColumn( + pfs_group = tables.Column( verbose_name=_('PFS Group') ) tags = columns.TagColumn( @@ -228,7 +228,7 @@ class IPSecProfileTable(NetBoxTable): verbose_name=_('Name'), linkify=True ) - mode = columns.ChoiceFieldColumn( + mode = tables.Column( verbose_name=_('Mode') ) ike_policy = tables.Column(