netbox-plugin-dns 1.2.6__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 (62) 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 +1 -0
  15. netbox_dns/fields/choice_array.py +20 -0
  16. netbox_dns/filtersets/__init__.py +3 -0
  17. netbox_dns/filtersets/dnssec_key_template.py +51 -0
  18. netbox_dns/filtersets/dnssec_policy.py +73 -0
  19. netbox_dns/filtersets/zone.py +23 -4
  20. netbox_dns/filtersets/zone_template.py +11 -0
  21. netbox_dns/forms/__init__.py +2 -0
  22. netbox_dns/forms/dnssec_key_template.py +188 -0
  23. netbox_dns/forms/dnssec_policy.py +563 -0
  24. netbox_dns/forms/zone.py +48 -0
  25. netbox_dns/forms/zone_template.py +29 -0
  26. netbox_dns/graphql/__init__.py +7 -3
  27. netbox_dns/graphql/filters.py +16 -0
  28. netbox_dns/graphql/schema.py +20 -0
  29. netbox_dns/graphql/types.py +67 -3
  30. netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
  31. netbox_dns/locale/fr/LC_MESSAGES/django.mo +0 -0
  32. netbox_dns/migrations/0015_dnssec.py +168 -0
  33. netbox_dns/migrations/0016_dnssec_policy_status.py +18 -0
  34. netbox_dns/migrations/0017_dnssec_policy_zone_zone_template.py +41 -0
  35. netbox_dns/models/__init__.py +2 -0
  36. netbox_dns/models/dnssec_key_template.py +114 -0
  37. netbox_dns/models/dnssec_policy.py +201 -0
  38. netbox_dns/models/zone.py +29 -16
  39. netbox_dns/models/zone_template.py +16 -6
  40. netbox_dns/navigation.py +49 -0
  41. netbox_dns/signals/dnssec.py +32 -0
  42. netbox_dns/tables/__init__.py +2 -0
  43. netbox_dns/tables/dnssec_key_template.py +48 -0
  44. netbox_dns/tables/dnssec_policy.py +131 -0
  45. netbox_dns/tables/zone.py +17 -1
  46. netbox_dns/tables/zone_template.py +4 -0
  47. netbox_dns/templates/netbox_dns/dnsseckeytemplate.html +70 -0
  48. netbox_dns/templates/netbox_dns/dnssecpolicy.html +155 -0
  49. netbox_dns/templates/netbox_dns/zone.html +16 -0
  50. netbox_dns/templates/netbox_dns/zonetemplate/child.html +46 -0
  51. netbox_dns/templates/netbox_dns/zonetemplate.html +12 -0
  52. netbox_dns/urls.py +16 -0
  53. netbox_dns/validators/__init__.py +1 -0
  54. netbox_dns/validators/dnssec.py +146 -0
  55. netbox_dns/views/__init__.py +2 -0
  56. netbox_dns/views/dnssec_key_template.py +87 -0
  57. netbox_dns/views/dnssec_policy.py +153 -0
  58. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/METADATA +2 -2
  59. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/RECORD +62 -38
  60. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/LICENSE +0 -0
  61. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/WHEEL +0 -0
  62. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7b2.dist-info}/top_level.txt +0 -0
@@ -27,6 +27,7 @@ from netbox_dns.models import (
27
27
  NameServer,
28
28
  Registrar,
29
29
  RegistrationContact,
30
+ DNSSECPolicy,
30
31
  )
31
32
 
32
33
 
@@ -62,6 +63,7 @@ class ZoneTemplateForm(TenancyForm, NetBoxModelForm):
62
63
  FieldSet("name", "description", "nameservers", name=_("Zone Template")),
63
64
  FieldSet("soa_mname", "soa_rname", name=_("SOA")),
64
65
  FieldSet("record_templates", name=_("Record Templates")),
66
+ FieldSet("dnssec_policy", name=_("DNSSEC")),
65
67
  FieldSet(
66
68
  "registrar",
67
69
  "registrant",
@@ -82,6 +84,7 @@ class ZoneTemplateForm(TenancyForm, NetBoxModelForm):
82
84
  "nameservers",
83
85
  "soa_mname",
84
86
  "soa_rname",
87
+ "dnssec_policy",
85
88
  "record_templates",
86
89
  "description",
87
90
  "registrar",
@@ -105,6 +108,7 @@ class ZoneTemplateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
105
108
  FieldSet("name", "nameserver_id", "description", name=_("Attributes")),
106
109
  FieldSet("soa_mname_id", "soa_rname", name=_("SOA")),
107
110
  FieldSet("record_template_id", name=_("Record Templates")),
111
+ FieldSet("dnssec_policy", name=_("DNSSEC")),
108
112
  FieldSet(
109
113
  "registrar_id",
110
114
  "registrant_id",
@@ -142,6 +146,11 @@ class ZoneTemplateFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
142
146
  description = forms.CharField(
143
147
  required=False,
144
148
  )
149
+ dnssec_policy_id = DynamicModelMultipleChoiceField(
150
+ queryset=DNSSECPolicy.objects.all(),
151
+ required=False,
152
+ label=_("DNSSEC Policy ID"),
153
+ )
145
154
  registrar_id = DynamicModelMultipleChoiceField(
146
155
  queryset=Registrar.objects.all(),
147
156
  required=False,
@@ -189,6 +198,15 @@ class ZoneTemplateImportForm(NetBoxModelImportForm):
189
198
  required=False,
190
199
  label=_("Record Templates"),
191
200
  )
201
+ dnssec_policy = CSVModelChoiceField(
202
+ queryset=DNSSECPolicy.objects.all(),
203
+ required=False,
204
+ to_field_name="name",
205
+ error_messages={
206
+ "invalid_choice": _("DNSSEC policy %(value)s not found"),
207
+ },
208
+ label=_("DNSSEC Policy"),
209
+ )
192
210
  registrar = CSVModelChoiceField(
193
211
  queryset=Registrar.objects.all(),
194
212
  required=False,
@@ -250,6 +268,7 @@ class ZoneTemplateImportForm(NetBoxModelImportForm):
250
268
  "soa_mname",
251
269
  "soa_rname",
252
270
  "record_templates",
271
+ "dnssec_policy",
253
272
  "description",
254
273
  "registrar",
255
274
  "registrant",
@@ -281,6 +300,11 @@ class ZoneTemplateBulkEditForm(NetBoxModelBulkEditForm):
281
300
  description = forms.CharField(
282
301
  max_length=200, required=False, label=_("Description")
283
302
  )
303
+ dnssec_policy = DynamicModelChoiceField(
304
+ queryset=DNSSECPolicy.objects.all(),
305
+ required=False,
306
+ label=_("DNSSEC Policy"),
307
+ )
284
308
  registrar = DynamicModelChoiceField(
285
309
  queryset=Registrar.objects.all(),
286
310
  required=False,
@@ -334,6 +358,10 @@ class ZoneTemplateBulkEditForm(NetBoxModelBulkEditForm):
334
358
  "record_templates",
335
359
  name=_("Record Templates"),
336
360
  ),
361
+ FieldSet(
362
+ "dnssec_policy",
363
+ name=_("DNSSEC"),
364
+ ),
337
365
  FieldSet(
338
366
  "registrar",
339
367
  "registrant",
@@ -351,6 +379,7 @@ class ZoneTemplateBulkEditForm(NetBoxModelBulkEditForm):
351
379
  "soa_mname",
352
380
  "soa_rname",
353
381
  "record_templates",
382
+ "dnssec_policy",
354
383
  "registrar",
355
384
  "registrant",
356
385
  "admin_c",
@@ -1,10 +1,12 @@
1
1
  from .schema import (
2
- NetBoxDNSViewQuery,
3
2
  NetBoxDNSNameServerQuery,
4
- NetBoxDNSRegistrationContactQuery,
5
- NetBoxDNSRegistrarQuery,
3
+ NetBoxDNSViewQuery,
6
4
  NetBoxDNSZoneQuery,
7
5
  NetBoxDNSRecordQuery,
6
+ NetBoxDNSDNSSECKeyTemplateQuery,
7
+ NetBoxDNSDNSSECPolicyQuery,
8
+ NetBoxDNSRegistrationContactQuery,
9
+ NetBoxDNSRegistrarQuery,
8
10
  NetBoxDNSZoneTemplateQuery,
9
11
  NetBoxDNSRecordTemplateQuery,
10
12
  )
@@ -14,6 +16,8 @@ schema = [
14
16
  NetBoxDNSViewQuery,
15
17
  NetBoxDNSZoneQuery,
16
18
  NetBoxDNSRecordQuery,
19
+ NetBoxDNSDNSSECKeyTemplateQuery,
20
+ NetBoxDNSDNSSECPolicyQuery,
17
21
  NetBoxDNSRegistrationContactQuery,
18
22
  NetBoxDNSRegistrarQuery,
19
23
  NetBoxDNSZoneTemplateQuery,
@@ -7,6 +7,8 @@ from netbox_dns.models import (
7
7
  View,
8
8
  Zone,
9
9
  Record,
10
+ DNSSECKeyTemplate,
11
+ DNSSECPolicy,
10
12
  RegistrationContact,
11
13
  Registrar,
12
14
  ZoneTemplate,
@@ -17,6 +19,8 @@ from netbox_dns.filtersets import (
17
19
  ViewFilterSet,
18
20
  ZoneFilterSet,
19
21
  RecordFilterSet,
22
+ DNSSECKeyTemplateFilterSet,
23
+ DNSSECPolicyFilterSet,
20
24
  RegistrationContactFilterSet,
21
25
  RegistrarFilterSet,
22
26
  ZoneTemplateFilterSet,
@@ -48,6 +52,18 @@ class NetBoxDNSRecordFilter(BaseFilterMixin):
48
52
  ip_address: str | None
49
53
 
50
54
 
55
+ @strawberry_django.filter(DNSSECKeyTemplate, lookups=True)
56
+ @autotype_decorator(DNSSECKeyTemplateFilterSet)
57
+ class NetBoxDNSDNSSECKeyTemplateFilter(BaseFilterMixin):
58
+ ip_address: str | None
59
+
60
+
61
+ @strawberry_django.filter(DNSSECPolicy, lookups=True)
62
+ @autotype_decorator(DNSSECPolicyFilterSet)
63
+ class NetBoxDNSDNSSECPolicyFilter(BaseFilterMixin):
64
+ ip_address: str | None
65
+
66
+
51
67
  @strawberry_django.filter(ZoneTemplate, lookups=True)
52
68
  @autotype_decorator(ZoneTemplateFilterSet)
53
69
  class NetBoxDNSZoneTemplateFilter(BaseFilterMixin):
@@ -8,6 +8,8 @@ from .types import (
8
8
  NetBoxDNSViewType,
9
9
  NetBoxDNSZoneType,
10
10
  NetBoxDNSRecordType,
11
+ NetBoxDNSDNSSECKeyTemplateType,
12
+ NetBoxDNSDNSSECPolicyType,
11
13
  NetBoxDNSRegistrationContactType,
12
14
  NetBoxDNSRegistrarType,
13
15
  NetBoxDNSZoneTemplateType,
@@ -41,6 +43,24 @@ class NetBoxDNSRecordQuery:
41
43
  netbox_dns_record_list: List[NetBoxDNSRecordType] = strawberry_django.field()
42
44
 
43
45
 
46
+ @strawberry.type(name="Query")
47
+ class NetBoxDNSDNSSECKeyTemplateQuery:
48
+ netbox_dns_dnssec_key_template: NetBoxDNSDNSSECKeyTemplateType = (
49
+ strawberry_django.field()
50
+ )
51
+ netbox_dns_dnssec_key_template_list: List[NetBoxDNSDNSSECKeyTemplateType] = (
52
+ strawberry_django.field()
53
+ )
54
+
55
+
56
+ @strawberry.type(name="Query")
57
+ class NetBoxDNSDNSSECPolicyQuery:
58
+ netbox_dns_dnssec_policy: NetBoxDNSDNSSECPolicyType = strawberry_django.field()
59
+ netbox_dns_dnssec_policy_list: List[NetBoxDNSDNSSECPolicyType] = (
60
+ strawberry_django.field()
61
+ )
62
+
63
+
44
64
  @strawberry.type(name="Query")
45
65
  class NetBoxDNSRegistrationContactQuery:
46
66
  netbox_dns_registration_contact: NetBoxDNSRegistrationContactType = (
@@ -13,6 +13,8 @@ from netbox_dns.models import (
13
13
  View,
14
14
  Zone,
15
15
  Record,
16
+ DNSSECKeyTemplate,
17
+ DNSSECPolicy,
16
18
  RegistrationContact,
17
19
  Registrar,
18
20
  ZoneTemplate,
@@ -23,6 +25,8 @@ from .filters import (
23
25
  NetBoxDNSViewFilter,
24
26
  NetBoxDNSZoneFilter,
25
27
  NetBoxDNSRecordFilter,
28
+ NetBoxDNSDNSSECKeyTemplateFilter,
29
+ NetBoxDNSDNSSECPolicyFilter,
26
30
  NetBoxDNSRegistrationContactFilter,
27
31
  NetBoxDNSRegistrarFilter,
28
32
  NetBoxDNSZoneTemplateFilter,
@@ -58,6 +62,7 @@ class NetBoxDNSViewType(NetBoxObjectType):
58
62
  @strawberry_django.type(Zone, fields="__all__", filters=NetBoxDNSZoneFilter)
59
63
  class NetBoxDNSZoneType(NetBoxObjectType):
60
64
  name: str
65
+ description: str | None
61
66
  status: str
62
67
  active: bool
63
68
  view: Annotated["NetBoxDNSViewType", strawberry.lazy("netbox_dns.graphql.types")]
@@ -78,9 +83,13 @@ class NetBoxDNSZoneType(NetBoxObjectType):
78
83
  soa_expire: BigInt
79
84
  soa_minimum: BigInt
80
85
  soa_serial_auto: bool
81
- description: str | None
82
- arpa_network: str | None
83
- tenant: Annotated["TenantType", strawberry.lazy("tenancy.graphql.types")] | None
86
+ dnssec_policy: (
87
+ Annotated[
88
+ "NetBoxDNSDNSSECPolicyType", strawberry.lazy("netbox_dns.graphql.types")
89
+ ]
90
+ | None
91
+ )
92
+ inline_signing: bool
84
93
  registrar: (
85
94
  Annotated["NetBoxDNSRegistrarType", strawberry.lazy("netbox_dns.graphql.types")]
86
95
  | None
@@ -126,6 +135,8 @@ class NetBoxDNSZoneType(NetBoxObjectType):
126
135
  rfc2317_child_zones: List[
127
136
  Annotated["NetBoxDNSRecordType", strawberry.lazy("netbox_dns.graphql.types")]
128
137
  ]
138
+ arpa_network: str | None
139
+ tenant: Annotated["TenantType", strawberry.lazy("tenancy.graphql.types")] | None
129
140
 
130
141
 
131
142
  @strawberry_django.type(Record, fields="__all__", filters=NetBoxDNSRecordFilter)
@@ -162,6 +173,53 @@ class NetBoxDNSRecordType(NetBoxObjectType):
162
173
  ]
163
174
 
164
175
 
176
+ @strawberry_django.type(
177
+ DNSSECKeyTemplate, fields="__all__", filters=NetBoxDNSDNSSECKeyTemplateFilter
178
+ )
179
+ class NetBoxDNSDNSSECKeyTemplateType(NetBoxObjectType):
180
+ name: str
181
+ description: str
182
+ tenant: Annotated["TenantType", strawberry.lazy("tenancy.graphql.types")] | None
183
+ type: str
184
+ lifetime: BigInt | None
185
+ algorithm: str
186
+ key_size: BigInt | None
187
+
188
+
189
+ @strawberry_django.type(
190
+ DNSSECPolicy, fields="__all__", filters=NetBoxDNSDNSSECPolicyFilter
191
+ )
192
+ class NetBoxDNSDNSSECPolicyType(NetBoxObjectType):
193
+ name: str
194
+ description: str | None
195
+ status: str
196
+ tenant: Annotated["TenantType", strawberry.lazy("tenancy.graphql.types")] | None
197
+ key_templates: List[
198
+ Annotated[
199
+ "NetBoxDNSDNSSECKeyTemplateType",
200
+ strawberry.lazy("netbox_dns.graphql.types"),
201
+ ]
202
+ ]
203
+ dnskey_ttl: BigInt | None
204
+ purge_keys: BigInt | None
205
+ publish_safety: BigInt | None
206
+ retire_safety: BigInt | None
207
+ signatures_jitter: BigInt | None
208
+ signatures_refresh: BigInt | None
209
+ signatures_validity: BigInt | None
210
+ signatures_validity_dnskey: BigInt | None
211
+ max_zone_ttl: BigInt | None
212
+ zone_propagation_delay: BigInt | None
213
+ create_cdnskey: bool
214
+ cds_digest_types: List[str]
215
+ parent_ds_ttl: BigInt | None
216
+ parent_propagation_delay: BigInt | None
217
+ use_nsec3: bool
218
+ nsec3_iterations: BigInt | None
219
+ nsec3_opt_out: bool
220
+ nsec3_salt_size: BigInt | None
221
+
222
+
165
223
  @strawberry_django.type(
166
224
  RegistrationContact, fields="__all__", filters=NetBoxDNSRegistrationContactFilter
167
225
  )
@@ -226,6 +284,12 @@ class NetBoxDNSZoneTemplateType(NetBoxObjectType):
226
284
  | None
227
285
  )
228
286
  soa_rname: str | None
287
+ dnssec_policy: (
288
+ Annotated[
289
+ "NetBoxDNSDNSSECPolicyType", strawberry.lazy("netbox_dns.graphql.types")
290
+ ]
291
+ | None
292
+ )
229
293
  record_templates: List[
230
294
  Annotated[
231
295
  "NetBoxDNSRecordTemplateType", strawberry.lazy("netbox_dns.graphql.types")
Binary file
Binary file
@@ -0,0 +1,168 @@
1
+ # Generated by Django 5.1.6 on 2025-03-04 12:09
2
+
3
+ import django.db.models.deletion
4
+ import netbox_dns.fields.choice_array
5
+ import taggit.managers
6
+ import utilities.json
7
+ from django.db import migrations, models
8
+
9
+
10
+ class Migration(migrations.Migration):
11
+
12
+ dependencies = [
13
+ ("extras", "0122_charfield_null_choices"),
14
+ ("netbox_dns", "0014_alter_unique_constraints_lowercase"),
15
+ ("tenancy", "0017_natural_ordering"),
16
+ ]
17
+
18
+ operations = [
19
+ migrations.CreateModel(
20
+ name="DNSSECKeyTemplate",
21
+ fields=[
22
+ (
23
+ "id",
24
+ models.BigAutoField(
25
+ auto_created=True, primary_key=True, serialize=False
26
+ ),
27
+ ),
28
+ ("created", models.DateTimeField(auto_now_add=True, null=True)),
29
+ ("last_updated", models.DateTimeField(auto_now=True, null=True)),
30
+ (
31
+ "custom_field_data",
32
+ models.JSONField(
33
+ blank=True,
34
+ default=dict,
35
+ encoder=utilities.json.CustomFieldJSONEncoder,
36
+ ),
37
+ ),
38
+ ("name", models.CharField(max_length=255)),
39
+ ("description", models.CharField(blank=True, max_length=200)),
40
+ ("type", models.CharField(max_length=3)),
41
+ ("lifetime", models.PositiveIntegerField(blank=True, null=True)),
42
+ ("algorithm", models.CharField()),
43
+ ("key_size", models.PositiveIntegerField(blank=True, null=True)),
44
+ (
45
+ "tags",
46
+ taggit.managers.TaggableManager(
47
+ through="extras.TaggedItem", to="extras.Tag"
48
+ ),
49
+ ),
50
+ (
51
+ "tenant",
52
+ models.ForeignKey(
53
+ blank=True,
54
+ null=True,
55
+ on_delete=django.db.models.deletion.PROTECT,
56
+ related_name="netbox_dns_dnssec_key_templates",
57
+ to="tenancy.tenant",
58
+ ),
59
+ ),
60
+ ],
61
+ options={
62
+ "verbose_name": "DNSSEC Key Template",
63
+ "verbose_name_plural": "DNSSEC Key Templates",
64
+ "ordering": ("name",),
65
+ "unique_together": {("name", "type")},
66
+ },
67
+ ),
68
+ migrations.CreateModel(
69
+ name="DNSSECPolicy",
70
+ fields=[
71
+ (
72
+ "id",
73
+ models.BigAutoField(
74
+ auto_created=True, primary_key=True, serialize=False
75
+ ),
76
+ ),
77
+ ("created", models.DateTimeField(auto_now_add=True, null=True)),
78
+ ("last_updated", models.DateTimeField(auto_now=True, null=True)),
79
+ (
80
+ "custom_field_data",
81
+ models.JSONField(
82
+ blank=True,
83
+ default=dict,
84
+ encoder=utilities.json.CustomFieldJSONEncoder,
85
+ ),
86
+ ),
87
+ ("name", models.CharField(max_length=255, unique=True)),
88
+ ("description", models.CharField(blank=True, max_length=200)),
89
+ ("dnskey_ttl", models.PositiveIntegerField(blank=True, null=True)),
90
+ ("purge_keys", models.PositiveIntegerField(blank=True, null=True)),
91
+ ("publish_safety", models.PositiveIntegerField(blank=True, null=True)),
92
+ ("retire_safety", models.PositiveIntegerField(blank=True, null=True)),
93
+ (
94
+ "signatures_jitter",
95
+ models.PositiveIntegerField(blank=True, null=True),
96
+ ),
97
+ (
98
+ "signatures_refresh",
99
+ models.PositiveIntegerField(blank=True, null=True),
100
+ ),
101
+ (
102
+ "signatures_validity",
103
+ models.PositiveIntegerField(blank=True, null=True),
104
+ ),
105
+ (
106
+ "signatures_validity_dnskey",
107
+ models.PositiveIntegerField(blank=True, null=True),
108
+ ),
109
+ ("max_zone_ttl", models.PositiveIntegerField(blank=True, null=True)),
110
+ (
111
+ "zone_propagation_delay",
112
+ models.PositiveIntegerField(blank=True, null=True),
113
+ ),
114
+ ("create_cdnskey", models.BooleanField(default=True)),
115
+ (
116
+ "cds_digest_types",
117
+ netbox_dns.fields.choice_array.ChoiceArrayField(
118
+ base_field=models.CharField(),
119
+ blank=True,
120
+ default=list,
121
+ null=True,
122
+ size=None,
123
+ ),
124
+ ),
125
+ ("parent_ds_ttl", models.PositiveIntegerField(blank=True, null=True)),
126
+ (
127
+ "parent_propagation_delay",
128
+ models.PositiveIntegerField(blank=True, null=True),
129
+ ),
130
+ ("use_nsec3", models.BooleanField(default=True)),
131
+ (
132
+ "nsec3_iterations",
133
+ models.PositiveIntegerField(blank=True, null=True),
134
+ ),
135
+ ("nsec3_opt_out", models.BooleanField(default=False)),
136
+ ("nsec3_salt_size", models.PositiveIntegerField(blank=True, null=True)),
137
+ (
138
+ "key_templates",
139
+ models.ManyToManyField(
140
+ blank=True,
141
+ related_name="policies",
142
+ to="netbox_dns.dnsseckeytemplate",
143
+ ),
144
+ ),
145
+ (
146
+ "tags",
147
+ taggit.managers.TaggableManager(
148
+ through="extras.TaggedItem", to="extras.Tag"
149
+ ),
150
+ ),
151
+ (
152
+ "tenant",
153
+ models.ForeignKey(
154
+ blank=True,
155
+ null=True,
156
+ on_delete=django.db.models.deletion.PROTECT,
157
+ related_name="netbox_dns_dnssec_policy",
158
+ to="tenancy.tenant",
159
+ ),
160
+ ),
161
+ ],
162
+ options={
163
+ "verbose_name": "DNSSEC Policy",
164
+ "verbose_name_plural": "DNSSEC Policies",
165
+ "ordering": ("name",),
166
+ },
167
+ ),
168
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 5.1.7 on 2025-03-09 18:23
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("netbox_dns", "0015_dnssec"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name="dnssecpolicy",
15
+ name="status",
16
+ field=models.CharField(default="active"),
17
+ ),
18
+ ]
@@ -0,0 +1,41 @@
1
+ # Generated by Django 5.1.6 on 2025-03-10 15:40
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("netbox_dns", "0016_dnssec_policy_status"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name="zone",
16
+ name="dnssec_policy",
17
+ field=models.ForeignKey(
18
+ blank=True,
19
+ null=True,
20
+ on_delete=django.db.models.deletion.PROTECT,
21
+ related_name="zones",
22
+ to="netbox_dns.dnssecpolicy",
23
+ ),
24
+ ),
25
+ migrations.AddField(
26
+ model_name="zone",
27
+ name="inline_signing",
28
+ field=models.BooleanField(default=True),
29
+ ),
30
+ migrations.AddField(
31
+ model_name="zonetemplate",
32
+ name="dnssec_policy",
33
+ field=models.ForeignKey(
34
+ blank=True,
35
+ null=True,
36
+ on_delete=django.db.models.deletion.SET_NULL,
37
+ related_name="zone_templates",
38
+ to="netbox_dns.dnssecpolicy",
39
+ ),
40
+ ),
41
+ ]
@@ -6,3 +6,5 @@ from .registration_contact import *
6
6
  from .registrar import *
7
7
  from .zone_template import *
8
8
  from .record_template import *
9
+ from .dnssec_key_template import *
10
+ from .dnssec_policy import *
@@ -0,0 +1,114 @@
1
+ from django.db import models
2
+ from django.urls import reverse
3
+ from django.utils.translation import gettext_lazy as _
4
+
5
+ from netbox.models import NetBoxModel
6
+ from netbox.search import SearchIndex, register_search
7
+ from netbox.models.features import ContactsMixin
8
+
9
+ from netbox_dns.choices import (
10
+ DNSSECKeyTemplateTypeChoices,
11
+ DNSSECKeyTemplateAlgorithmChoices,
12
+ DNSSECKeyTemplateKeySizeChoices,
13
+ )
14
+ from netbox_dns.validators import validate_key_template
15
+
16
+
17
+ __all__ = (
18
+ "DNSSECKeyTemplate",
19
+ "DNSSECKeyTemplateIndex",
20
+ )
21
+
22
+
23
+ class DNSSECKeyTemplate(ContactsMixin, NetBoxModel):
24
+ name = models.CharField(
25
+ verbose_name=_("Name"),
26
+ max_length=255,
27
+ )
28
+ description = models.CharField(
29
+ verbose_name=_("Description"),
30
+ max_length=200,
31
+ blank=True,
32
+ )
33
+
34
+ type = models.CharField(
35
+ verbose_name=_("Type"),
36
+ choices=DNSSECKeyTemplateTypeChoices,
37
+ max_length=3,
38
+ blank=False,
39
+ null=False,
40
+ )
41
+ lifetime = models.PositiveIntegerField(
42
+ verbose_name=_("Lifetime"),
43
+ blank=True,
44
+ null=True,
45
+ )
46
+ algorithm = models.CharField(
47
+ verbose_name=_("Algorithm"),
48
+ choices=DNSSECKeyTemplateAlgorithmChoices,
49
+ blank=False,
50
+ null=False,
51
+ )
52
+ key_size = models.PositiveIntegerField(
53
+ verbose_name=_("Key Size"),
54
+ choices=DNSSECKeyTemplateKeySizeChoices,
55
+ blank=True,
56
+ null=True,
57
+ )
58
+
59
+ tenant = models.ForeignKey(
60
+ verbose_name=_("Tenant"),
61
+ to="tenancy.Tenant",
62
+ on_delete=models.PROTECT,
63
+ related_name="netbox_dns_dnssec_key_templates",
64
+ blank=True,
65
+ null=True,
66
+ )
67
+
68
+ clone_fields = (
69
+ "description",
70
+ "type",
71
+ "lifetime",
72
+ "algorithm",
73
+ "key_size",
74
+ "tenant",
75
+ )
76
+
77
+ class Meta:
78
+ verbose_name = _("DNSSEC Key Template")
79
+ verbose_name_plural = _("DNSSEC Key Templates")
80
+ unique_together = (
81
+ "name",
82
+ "type",
83
+ )
84
+
85
+ ordering = ("name",)
86
+
87
+ def __str__(self):
88
+ return f"{str(self.name)} [{self.type}]"
89
+
90
+ # TODO: Remove in version 1.3.0 (NetBox #18555)
91
+ def get_absolute_url(self):
92
+ return reverse("plugins:netbox_dns:dnsseckeytemplate", kwargs={"pk": self.pk})
93
+
94
+ def get_type_color(self):
95
+ return DNSSECKeyTemplateTypeChoices.colors.get(self.type)
96
+
97
+ def clean(self, *args, **kwargs):
98
+ super().clean(*args, **kwargs)
99
+
100
+ validate_key_template(self)
101
+
102
+ def save(self, *args, **kwargs):
103
+ validate_key_template(self)
104
+
105
+ super().save(*args, **kwargs)
106
+
107
+
108
+ @register_search
109
+ class DNSSECKeyTemplateIndex(SearchIndex):
110
+ model = DNSSECKeyTemplate
111
+ fields = (
112
+ ("name", 100),
113
+ ("description", 500),
114
+ )