netbox-plugin-dns 1.2.5__py3-none-any.whl → 1.2.7b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of netbox-plugin-dns might be problematic. Click here for more details.

Files changed (65) hide show
  1. netbox_dns/__init__.py +15 -1
  2. netbox_dns/api/serializers.py +3 -0
  3. netbox_dns/api/serializers_/dnssec_key_template.py +46 -0
  4. netbox_dns/api/serializers_/dnssec_policy.py +83 -0
  5. netbox_dns/api/serializers_/zone.py +10 -0
  6. netbox_dns/api/serializers_/zone_template.py +13 -4
  7. netbox_dns/api/urls.py +4 -0
  8. netbox_dns/api/views.py +18 -0
  9. netbox_dns/choices/__init__.py +2 -0
  10. netbox_dns/choices/dnssec_key_template.py +63 -0
  11. netbox_dns/choices/dnssec_policy.py +40 -0
  12. netbox_dns/choices/record.py +2 -25
  13. netbox_dns/choices/utilities.py +26 -0
  14. netbox_dns/fields/__init__.py +2 -0
  15. netbox_dns/fields/choice_array.py +20 -0
  16. netbox_dns/fields/timeperiod.py +31 -0
  17. netbox_dns/filtersets/__init__.py +3 -0
  18. netbox_dns/filtersets/dnssec_key_template.py +51 -0
  19. netbox_dns/filtersets/dnssec_policy.py +73 -0
  20. netbox_dns/filtersets/zone.py +23 -4
  21. netbox_dns/filtersets/zone_template.py +11 -0
  22. netbox_dns/forms/__init__.py +2 -0
  23. netbox_dns/forms/dnssec_key_template.py +188 -0
  24. netbox_dns/forms/dnssec_policy.py +563 -0
  25. netbox_dns/forms/record.py +12 -6
  26. netbox_dns/forms/record_template.py +9 -3
  27. netbox_dns/forms/zone.py +70 -22
  28. netbox_dns/forms/zone_template.py +29 -0
  29. netbox_dns/graphql/__init__.py +7 -3
  30. netbox_dns/graphql/filters.py +16 -0
  31. netbox_dns/graphql/schema.py +20 -0
  32. netbox_dns/graphql/types.py +67 -3
  33. netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
  34. netbox_dns/locale/fr/LC_MESSAGES/django.mo +0 -0
  35. netbox_dns/migrations/0015_dnssec.py +168 -0
  36. netbox_dns/migrations/0016_dnssec_policy_status.py +18 -0
  37. netbox_dns/migrations/0017_dnssec_policy_zone_zone_template.py +41 -0
  38. netbox_dns/models/__init__.py +2 -0
  39. netbox_dns/models/dnssec_key_template.py +114 -0
  40. netbox_dns/models/dnssec_policy.py +201 -0
  41. netbox_dns/models/zone.py +29 -16
  42. netbox_dns/models/zone_template.py +16 -6
  43. netbox_dns/navigation.py +49 -0
  44. netbox_dns/signals/dnssec.py +32 -0
  45. netbox_dns/tables/__init__.py +2 -0
  46. netbox_dns/tables/dnssec_key_template.py +48 -0
  47. netbox_dns/tables/dnssec_policy.py +131 -0
  48. netbox_dns/tables/zone.py +17 -1
  49. netbox_dns/tables/zone_template.py +4 -0
  50. netbox_dns/templates/netbox_dns/dnsseckeytemplate.html +70 -0
  51. netbox_dns/templates/netbox_dns/dnssecpolicy.html +155 -0
  52. netbox_dns/templates/netbox_dns/zone.html +16 -0
  53. netbox_dns/templates/netbox_dns/zonetemplate/child.html +46 -0
  54. netbox_dns/templates/netbox_dns/zonetemplate.html +12 -0
  55. netbox_dns/urls.py +16 -0
  56. netbox_dns/validators/__init__.py +1 -0
  57. netbox_dns/validators/dnssec.py +146 -0
  58. netbox_dns/views/__init__.py +2 -0
  59. netbox_dns/views/dnssec_key_template.py +87 -0
  60. netbox_dns/views/dnssec_policy.py +153 -0
  61. {netbox_plugin_dns-1.2.5.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/METADATA +2 -2
  62. {netbox_plugin_dns-1.2.5.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/RECORD +65 -39
  63. {netbox_plugin_dns-1.2.5.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/WHEEL +1 -1
  64. {netbox_plugin_dns-1.2.5.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/LICENSE +0 -0
  65. {netbox_plugin_dns-1.2.5.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/top_level.txt +0 -0
netbox_dns/__init__.py CHANGED
@@ -7,7 +7,7 @@ from ipam.choices import IPAddressStatusChoices
7
7
 
8
8
  from netbox_dns.choices import RecordTypeChoices, RecordStatusChoices, ZoneStatusChoices
9
9
 
10
- __version__ = "1.2.5"
10
+ __version__ = "1.2.7-beta2"
11
11
 
12
12
 
13
13
  def _check_list(setting):
@@ -65,12 +65,26 @@ class DNSConfig(PluginConfig):
65
65
  "menu_name": "DNS",
66
66
  "top_level_menu": True,
67
67
  "convert_names_to_lowercase": False,
68
+ "dnssec_purge_keys": 7776000, # P90D
69
+ "dnssec_publish_safety": 3600, # PT1H
70
+ "dnssec_retire_safety": 3600, # PT1H
71
+ "dnssec_signatures_jitter": 43200, # PT12H
72
+ "dnssec_signatures_refresh": 432000, # P5D
73
+ "dnssec_signatures_validity": 1209600, # P14D
74
+ "dnssec_signatures_validity_dnskey": 1209600, # P14D
75
+ "dnssec_max_zone_ttl": 86400, # P1D
76
+ "dnssec_zone_propagation_delay": 300, # PT5M
77
+ "dnssec_parent_ds_ttl": 86400, # P1D
78
+ "dnssec_parent_propagation_delay": 3600, # PT1H
79
+ "dnssec_dnskey_ttl": 3600, # PT1H
68
80
  }
69
81
  base_url = "netbox-dns"
70
82
 
71
83
  def ready(self):
72
84
  super().ready()
73
85
 
86
+ import netbox_dns.signals.dnssec # noqa: F401
87
+
74
88
  if not get_plugin_config("netbox_dns", "dnssync_disabled"):
75
89
  import netbox_dns.signals.ipam_dnssync # noqa: F401
76
90
  import netbox_dns.tables.ipam_dnssync # noqa: F401
@@ -6,6 +6,9 @@ from .serializers_.view import *
6
6
  from .serializers_.zone import *
7
7
  from .serializers_.zone_template import *
8
8
  from .serializers_.record_template import *
9
+ from .serializers_.dnssec_key_template import *
10
+ from .serializers_.dnssec_policy import *
11
+
9
12
  from .serializers_.prefix import *
10
13
 
11
14
  from .nested_serializers import *
@@ -0,0 +1,46 @@
1
+ from rest_framework import serializers
2
+
3
+ from netbox.api.serializers import NetBoxModelSerializer
4
+ from tenancy.api.serializers_.tenants import TenantSerializer
5
+
6
+ from netbox_dns.models import DNSSECKeyTemplate
7
+
8
+
9
+ __all__ = ("DNSSECKeyTemplateSerializer",)
10
+
11
+
12
+ class DNSSECKeyTemplateSerializer(NetBoxModelSerializer):
13
+ url = serializers.HyperlinkedIdentityField(
14
+ view_name="plugins-api:netbox_dns-api:dnsseckeytemplate-detail"
15
+ )
16
+ tenant = TenantSerializer(required=False, allow_null=True)
17
+
18
+ class Meta:
19
+ model = DNSSECKeyTemplate
20
+ fields = (
21
+ "id",
22
+ "url",
23
+ "display",
24
+ "name",
25
+ "description",
26
+ "tags",
27
+ "type",
28
+ "lifetime",
29
+ "algorithm",
30
+ "key_size",
31
+ "created",
32
+ "last_updated",
33
+ "custom_fields",
34
+ "tenant",
35
+ )
36
+ brief_fields = (
37
+ "id",
38
+ "url",
39
+ "display",
40
+ "name",
41
+ "type",
42
+ "lifetime",
43
+ "algorithm",
44
+ "key_size",
45
+ "description",
46
+ )
@@ -0,0 +1,83 @@
1
+ from django.utils.translation import gettext as _
2
+ from rest_framework import serializers
3
+
4
+ from netbox.api.serializers import NetBoxModelSerializer
5
+ from tenancy.api.serializers_.tenants import TenantSerializer
6
+
7
+ from netbox_dns.models import DNSSECPolicy
8
+
9
+ from .dnssec_key_template import DNSSECKeyTemplateSerializer
10
+
11
+
12
+ __all__ = ("DNSSECPolicySerializer",)
13
+
14
+
15
+ class DNSSECPolicySerializer(NetBoxModelSerializer):
16
+ url = serializers.HyperlinkedIdentityField(
17
+ view_name="plugins-api:netbox_dns-api:dnssecpolicy-detail"
18
+ )
19
+ key_templates = DNSSECKeyTemplateSerializer(
20
+ nested=True,
21
+ many=True,
22
+ read_only=False,
23
+ required=False,
24
+ default=None,
25
+ help_text=_("Key templates assigned to the policy"),
26
+ )
27
+ tenant = TenantSerializer(required=False, allow_null=True)
28
+
29
+ class Meta:
30
+ model = DNSSECPolicy
31
+ fields = (
32
+ "id",
33
+ "url",
34
+ "display",
35
+ "name",
36
+ "description",
37
+ "status",
38
+ "tags",
39
+ "key_templates",
40
+ "dnskey_ttl",
41
+ "purge_keys",
42
+ "publish_safety",
43
+ "retire_safety",
44
+ "signatures_jitter",
45
+ "signatures_refresh",
46
+ "signatures_validity",
47
+ "signatures_validity_dnskey",
48
+ "max_zone_ttl",
49
+ "zone_propagation_delay",
50
+ "create_cdnskey",
51
+ "cds_digest_types",
52
+ "parent_ds_ttl",
53
+ "parent_propagation_delay",
54
+ "use_nsec3",
55
+ "nsec3_iterations",
56
+ "nsec3_opt_out",
57
+ "nsec3_salt_size",
58
+ "created",
59
+ "last_updated",
60
+ "custom_fields",
61
+ "tenant",
62
+ )
63
+ brief_fields = ("id", "url", "display", "name", "description", "status")
64
+
65
+ def create(self, validated_data):
66
+ dnssec_key_templates = validated_data.pop("key_templates", None)
67
+
68
+ dnssec_policy = super().create(validated_data)
69
+
70
+ if dnssec_key_templates is not None:
71
+ dnssec_policy.key_templates.set(dnssec_key_templates)
72
+
73
+ return dnssec_policy
74
+
75
+ def update(self, instance, validated_data):
76
+ dnssec_key_templates = validated_data.pop("key_templates", None)
77
+
78
+ dnssec_policy = super().update(instance, validated_data)
79
+
80
+ if dnssec_key_templates is not None:
81
+ dnssec_policy.key_templates.set(dnssec_key_templates)
82
+
83
+ return dnssec_policy
@@ -9,6 +9,7 @@ from .nameserver import NameServerSerializer
9
9
  from .registrar import RegistrarSerializer
10
10
  from .registration_contact import RegistrationContactSerializer
11
11
  from .zone_template import ZoneTemplateSerializer
12
+ from .dnssec_policy import DNSSECPolicySerializer
12
13
 
13
14
  from ..nested_serializers import NestedZoneSerializer
14
15
 
@@ -62,6 +63,13 @@ class ZoneSerializer(NetBoxModelSerializer):
62
63
  required=False,
63
64
  help_text=_("RFC2317 child zones of the zone"),
64
65
  )
66
+ dnssec_policy = DNSSECPolicySerializer(
67
+ nested=True,
68
+ many=False,
69
+ read_only=False,
70
+ required=False,
71
+ help_text=_("DNSSEC policy to apply to the zone"),
72
+ )
65
73
  registrar = RegistrarSerializer(
66
74
  nested=True,
67
75
  many=False,
@@ -173,6 +181,8 @@ class ZoneSerializer(NetBoxModelSerializer):
173
181
  "rfc2317_parent_managed",
174
182
  "rfc2317_parent_zone",
175
183
  "rfc2317_child_zones",
184
+ "dnssec_policy",
185
+ "inline_signing",
176
186
  "registrar",
177
187
  "registry_domain_id",
178
188
  "registrant",
@@ -10,6 +10,7 @@ from netbox_dns.api.nested_serializers import NestedRecordTemplateSerializer
10
10
  from .nameserver import NameServerSerializer
11
11
  from .registrar import RegistrarSerializer
12
12
  from .registration_contact import RegistrationContactSerializer
13
+ from .dnssec_policy import DNSSECPolicySerializer
13
14
 
14
15
 
15
16
  __all__ = ("ZoneTemplateSerializer",)
@@ -39,6 +40,13 @@ class ZoneTemplateSerializer(NetBoxModelSerializer):
39
40
  required=False,
40
41
  help_text=_("Record templates assigned to the zone template"),
41
42
  )
43
+ dnssec_policy = DNSSECPolicySerializer(
44
+ nested=True,
45
+ many=False,
46
+ read_only=False,
47
+ required=False,
48
+ help_text=_("DNSSEC policy assigned to the zone template"),
49
+ )
42
50
  registrar = RegistrarSerializer(
43
51
  nested=True,
44
52
  many=False,
@@ -113,20 +121,21 @@ class ZoneTemplateSerializer(NetBoxModelSerializer):
113
121
  "id",
114
122
  "url",
115
123
  "name",
124
+ "description",
116
125
  "display",
117
126
  "nameservers",
118
127
  "soa_mname",
119
128
  "soa_rname",
120
- "description",
121
- "tags",
122
- "created",
123
- "last_updated",
129
+ "dnssec_policy",
124
130
  "registrar",
125
131
  "registrant",
126
132
  "tech_c",
127
133
  "admin_c",
128
134
  "billing_c",
129
135
  "active",
136
+ "tags",
137
+ "created",
138
+ "last_updated",
130
139
  "custom_fields",
131
140
  "tenant",
132
141
  "record_templates",
netbox_dns/api/urls.py CHANGED
@@ -10,6 +10,8 @@ from netbox_dns.api.views import (
10
10
  RegistrationContactViewSet,
11
11
  ZoneTemplateViewSet,
12
12
  RecordTemplateViewSet,
13
+ DNSSECKeyTemplateViewSet,
14
+ DNSSECPolicyViewSet,
13
15
  PrefixViewSet,
14
16
  )
15
17
 
@@ -24,6 +26,8 @@ router.register("registrars", RegistrarViewSet)
24
26
  router.register("contacts", RegistrationContactViewSet)
25
27
  router.register("zonetemplates", ZoneTemplateViewSet)
26
28
  router.register("recordtemplates", RecordTemplateViewSet)
29
+ router.register("dnsseckeytemplates", DNSSECKeyTemplateViewSet)
30
+ router.register("dnssecpolicies", DNSSECPolicyViewSet)
27
31
 
28
32
  router.register("prefixes", PrefixViewSet)
29
33
 
netbox_dns/api/views.py CHANGED
@@ -16,6 +16,8 @@ from netbox_dns.api.serializers import (
16
16
  RegistrationContactSerializer,
17
17
  ZoneTemplateSerializer,
18
18
  RecordTemplateSerializer,
19
+ DNSSECKeyTemplateSerializer,
20
+ DNSSECPolicySerializer,
19
21
  PrefixSerializer,
20
22
  )
21
23
  from netbox_dns.filtersets import (
@@ -27,6 +29,8 @@ from netbox_dns.filtersets import (
27
29
  RegistrationContactFilterSet,
28
30
  ZoneTemplateFilterSet,
29
31
  RecordTemplateFilterSet,
32
+ DNSSECKeyTemplateFilterSet,
33
+ DNSSECPolicyFilterSet,
30
34
  )
31
35
  from netbox_dns.models import (
32
36
  View,
@@ -37,6 +41,8 @@ from netbox_dns.models import (
37
41
  RegistrationContact,
38
42
  ZoneTemplate,
39
43
  RecordTemplate,
44
+ DNSSECKeyTemplate,
45
+ DNSSECPolicy,
40
46
  )
41
47
 
42
48
 
@@ -135,6 +141,18 @@ class RecordTemplateViewSet(NetBoxModelViewSet):
135
141
  filterset_class = RecordTemplateFilterSet
136
142
 
137
143
 
144
+ class DNSSECKeyTemplateViewSet(NetBoxModelViewSet):
145
+ queryset = DNSSECKeyTemplate.objects.all()
146
+ serializer_class = DNSSECKeyTemplateSerializer
147
+ filterset_class = DNSSECKeyTemplateFilterSet
148
+
149
+
150
+ class DNSSECPolicyViewSet(NetBoxModelViewSet):
151
+ queryset = DNSSECPolicy.objects.all()
152
+ serializer_class = DNSSECPolicySerializer
153
+ filterset_class = DNSSECPolicyFilterSet
154
+
155
+
138
156
  class PrefixViewSet(NetBoxModelViewSet):
139
157
  queryset = Prefix.objects.all()
140
158
  serializer_class = PrefixSerializer
@@ -1,2 +1,4 @@
1
1
  from .record import *
2
2
  from .zone import *
3
+ from .dnssec_key_template import *
4
+ from .dnssec_policy import *
@@ -0,0 +1,63 @@
1
+ from dns.dnssectypes import Algorithm
2
+
3
+ from django.utils.translation import gettext_lazy as _
4
+
5
+ from utilities.choices import ChoiceSet
6
+
7
+ from .utilities import define_choice_attributes
8
+
9
+ DEPRECATED_ALGORITHMS = (
10
+ Algorithm.RSAMD5,
11
+ Algorithm.DH,
12
+ Algorithm.DSA,
13
+ Algorithm.ECC,
14
+ Algorithm.RSASHA1,
15
+ Algorithm.DSANSEC3SHA1,
16
+ Algorithm.RSASHA1NSEC3SHA1,
17
+ Algorithm.RSASHA512,
18
+ Algorithm.ECCGOST,
19
+ )
20
+
21
+
22
+ __all__ = (
23
+ "DNSSECKeyTemplateTypeChoices",
24
+ "DNSSECKeyTemplateAlgorithmChoices",
25
+ "DNSSECKeyTemplateKeySizeChoices",
26
+ )
27
+
28
+
29
+ class DNSSECKeyTemplateTypeChoices(ChoiceSet):
30
+ TYPE_CSK = "CSK"
31
+ TYPE_KSK = "KSK"
32
+ TYPE_ZSK = "ZSK"
33
+
34
+ CHOICES = [
35
+ (TYPE_CSK, _("CSK"), "purple"),
36
+ (TYPE_KSK, _("KSK"), "blue"),
37
+ (TYPE_ZSK, _("ZSK"), "green"),
38
+ ]
39
+
40
+
41
+ class DNSSECKeyTemplateKeySizeChoices(ChoiceSet):
42
+ SIZE_512 = 512
43
+ SIZE_1024 = 1024
44
+ SIZE_2048 = 2048
45
+ SIZE_3072 = 3072
46
+ SIZE_4096 = 4096
47
+
48
+ CHOICES = [
49
+ (SIZE_512, 512),
50
+ (SIZE_1024, 1024),
51
+ (SIZE_2048, 2048),
52
+ (SIZE_3072, 3072),
53
+ (SIZE_4096, 4096),
54
+ ]
55
+
56
+
57
+ @define_choice_attributes()
58
+ class DNSSECKeyTemplateAlgorithmChoices(ChoiceSet):
59
+ CHOICES = [
60
+ (algorithm.name, algorithm.name)
61
+ for algorithm in sorted(Algorithm, key=lambda a: a.name)
62
+ if algorithm.value < 252 and algorithm not in DEPRECATED_ALGORITHMS
63
+ ]
@@ -0,0 +1,40 @@
1
+ from dns.dnssectypes import DSDigest
2
+
3
+ from django.utils.translation import gettext_lazy as _
4
+
5
+ from utilities.choices import ChoiceSet
6
+
7
+ from .utilities import define_choice_attributes
8
+
9
+ DEPRECATED_DIGESTS = (
10
+ DSDigest.NULL,
11
+ DSDigest.SHA1,
12
+ DSDigest.GOST,
13
+ )
14
+
15
+
16
+ __all__ = (
17
+ "DNSSECPolicyDigestChoices",
18
+ "DNSSECPolicyStatusChoices",
19
+ )
20
+
21
+
22
+ @define_choice_attributes()
23
+ class DNSSECPolicyDigestChoices(ChoiceSet):
24
+ CHOICES = [
25
+ (digest.name, digest.name)
26
+ for digest in sorted(DSDigest, key=lambda a: a.name)
27
+ if digest not in DEPRECATED_DIGESTS
28
+ ]
29
+
30
+
31
+ class DNSSECPolicyStatusChoices(ChoiceSet):
32
+ key = "DNSSECPolicy.status"
33
+
34
+ STATUS_ACTIVE = "active"
35
+ STATUS_INACTIVE = "inactive"
36
+
37
+ CHOICES = [
38
+ (STATUS_ACTIVE, _("Active"), "blue"),
39
+ (STATUS_INACTIVE, _("Inactive"), "red"),
40
+ ]
@@ -1,11 +1,11 @@
1
1
  from dns import rdatatype, rdataclass
2
2
 
3
3
  from django.utils.translation import gettext_lazy as _
4
- from django.core.exceptions import ImproperlyConfigured
5
4
 
6
- from netbox.plugins.utils import get_plugin_config
7
5
  from utilities.choices import ChoiceSet
8
6
 
7
+ from .utilities import define_choice_attributes
8
+
9
9
 
10
10
  __all__ = (
11
11
  "RecordTypeChoices",
@@ -15,29 +15,6 @@ __all__ = (
15
15
  )
16
16
 
17
17
 
18
- def define_choice_attributes(filter_name=None):
19
- try:
20
- if filter_name is not None:
21
- filter_choices = get_plugin_config("netbox_dns", filter_name, [])
22
- else:
23
- filter_choices = []
24
- except ImproperlyConfigured:
25
- filter_choices = []
26
-
27
- def decorator(cls):
28
- choices = []
29
- for choice in cls._choices:
30
- if choice[0] not in filter_choices:
31
- setattr(cls, choice[0], choice[0])
32
- choices.append(choice)
33
- cls._choices = choices
34
- cls.CHOICES = choices
35
-
36
- return cls
37
-
38
- return decorator
39
-
40
-
41
18
  @define_choice_attributes()
42
19
  class RecordTypeChoices(ChoiceSet):
43
20
  CHOICES = [
@@ -0,0 +1,26 @@
1
+ from django.core.exceptions import ImproperlyConfigured
2
+
3
+ from netbox.plugins.utils import get_plugin_config
4
+
5
+
6
+ def define_choice_attributes(filter_name=None):
7
+ try:
8
+ if filter_name is not None:
9
+ filter_choices = get_plugin_config("netbox_dns", filter_name, [])
10
+ else:
11
+ filter_choices = []
12
+ except ImproperlyConfigured:
13
+ filter_choices = []
14
+
15
+ def decorator(cls):
16
+ choices = []
17
+ for choice in cls._choices:
18
+ if choice[0] not in filter_choices:
19
+ setattr(cls, choice[0], choice[0])
20
+ choices.append(choice)
21
+ cls._choices = choices
22
+ cls.CHOICES = choices
23
+
24
+ return cls
25
+
26
+ return decorator
@@ -2,3 +2,5 @@ from .network import *
2
2
  from .address import *
3
3
  from .rfc2317 import *
4
4
  from .ipam import *
5
+ from .choice_array import *
6
+ from .timeperiod import *
@@ -0,0 +1,20 @@
1
+ from django import forms
2
+ from django.contrib.postgres.fields import ArrayField
3
+
4
+
5
+ class _TypedMultipleChoiceField(forms.TypedMultipleChoiceField):
6
+ def __init__(self, *args, **kwargs):
7
+ kwargs.pop("base_field", None)
8
+ kwargs.pop("max_length", None)
9
+
10
+ super().__init__(*args, **kwargs)
11
+
12
+
13
+ class ChoiceArrayField(ArrayField):
14
+ def formfield(self, **kwargs):
15
+ return super().formfield(
16
+ form_class=_TypedMultipleChoiceField,
17
+ choices=self.base_field.choices,
18
+ coerce=self.base_field.to_python,
19
+ **kwargs,
20
+ )
@@ -0,0 +1,31 @@
1
+ from django.forms import Field
2
+ from django.utils.dateparse import parse_duration
3
+ from django.core.exceptions import ValidationError
4
+
5
+
6
+ __all__ = ("TimePeriodField",)
7
+
8
+
9
+ class TimePeriodField(Field):
10
+ def to_python(self, value):
11
+ if not value:
12
+ return None
13
+
14
+ try:
15
+ return int(value)
16
+ except ValueError:
17
+ try:
18
+ duration = parse_duration(value)
19
+ if duration is None:
20
+ raise TypeError
21
+ return int(duration.total_seconds())
22
+ except TypeError:
23
+ raise ValidationError(
24
+ "Enter a valid integer or ISO 8601 duration (W, M and Y are not supported)"
25
+ )
26
+
27
+ def validate(self, value):
28
+ super().validate(value)
29
+
30
+ if value is not None and value < 0:
31
+ raise ValidationError("A time period cannot be negative.")
@@ -7,3 +7,6 @@ from .registrar import *
7
7
 
8
8
  from .zone_template import *
9
9
  from .record_template import *
10
+
11
+ from .dnssec_key_template import *
12
+ from .dnssec_policy import *
@@ -0,0 +1,51 @@
1
+ import django_filters
2
+ from django.db.models import Q
3
+ from django.utils.translation import gettext as _
4
+
5
+ from netbox.filtersets import NetBoxModelFilterSet
6
+ from tenancy.filtersets import TenancyFilterSet
7
+
8
+ from netbox_dns.models import DNSSECKeyTemplate, DNSSECPolicy
9
+ from netbox_dns.choices import (
10
+ DNSSECKeyTemplateTypeChoices,
11
+ DNSSECKeyTemplateAlgorithmChoices,
12
+ DNSSECKeyTemplateKeySizeChoices,
13
+ )
14
+
15
+
16
+ __all__ = ("DNSSECKeyTemplateFilterSet",)
17
+
18
+
19
+ class DNSSECKeyTemplateFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
20
+ type = django_filters.MultipleChoiceFilter(
21
+ choices=DNSSECKeyTemplateTypeChoices,
22
+ )
23
+ algorithm = django_filters.MultipleChoiceFilter(
24
+ choices=DNSSECKeyTemplateAlgorithmChoices,
25
+ )
26
+ key_size = django_filters.MultipleChoiceFilter(
27
+ choices=DNSSECKeyTemplateKeySizeChoices,
28
+ )
29
+
30
+ policy_id = django_filters.ModelMultipleChoiceFilter(
31
+ field_name="policies",
32
+ queryset=DNSSECPolicy.objects.all(),
33
+ to_field_name="id",
34
+ label=_("DNSSEC Policy IDs"),
35
+ )
36
+ policy = django_filters.ModelMultipleChoiceFilter(
37
+ field_name="policies__name",
38
+ queryset=DNSSECPolicy.objects.all(),
39
+ to_field_name="name",
40
+ label=_("DNSSEC Policies"),
41
+ )
42
+
43
+ class Meta:
44
+ model = DNSSECKeyTemplate
45
+ fields = ("id", "name", "description", "lifetime")
46
+
47
+ def search(self, queryset, name, value):
48
+ if not value.strip():
49
+ return queryset
50
+ qs_filter = Q(name__icontains=value)
51
+ return queryset.filter(qs_filter)