netbox-plugin-dns 1.2.6__py3-none-any.whl → 1.2.7__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 (76) hide show
  1. netbox_dns/__init__.py +16 -8
  2. netbox_dns/api/field_serializers.py +25 -0
  3. netbox_dns/api/nested_serializers.py +19 -1
  4. netbox_dns/api/serializers.py +3 -0
  5. netbox_dns/api/serializers_/dnssec_key_template.py +59 -0
  6. netbox_dns/api/serializers_/dnssec_policy.py +113 -0
  7. netbox_dns/api/serializers_/record.py +2 -0
  8. netbox_dns/api/serializers_/record_template.py +2 -0
  9. netbox_dns/api/serializers_/zone.py +20 -1
  10. netbox_dns/api/serializers_/zone_template.py +13 -4
  11. netbox_dns/api/urls.py +4 -0
  12. netbox_dns/api/views.py +18 -0
  13. netbox_dns/choices/__init__.py +2 -0
  14. netbox_dns/choices/dnssec_key_template.py +63 -0
  15. netbox_dns/choices/dnssec_policy.py +40 -0
  16. netbox_dns/choices/record.py +2 -25
  17. netbox_dns/choices/utilities.py +26 -0
  18. netbox_dns/choices/zone.py +96 -1
  19. netbox_dns/fields/__init__.py +1 -0
  20. netbox_dns/fields/choice_array.py +33 -0
  21. netbox_dns/fields/timeperiod.py +15 -13
  22. netbox_dns/filtersets/__init__.py +3 -0
  23. netbox_dns/filtersets/dnssec_key_template.py +51 -0
  24. netbox_dns/filtersets/dnssec_policy.py +97 -0
  25. netbox_dns/filtersets/zone.py +30 -6
  26. netbox_dns/filtersets/zone_template.py +13 -2
  27. netbox_dns/forms/__init__.py +2 -0
  28. netbox_dns/forms/dnssec_key_template.py +189 -0
  29. netbox_dns/forms/dnssec_policy.py +593 -0
  30. netbox_dns/forms/nameserver.py +2 -0
  31. netbox_dns/forms/record_template.py +1 -0
  32. netbox_dns/forms/zone.py +120 -9
  33. netbox_dns/forms/zone_template.py +38 -0
  34. netbox_dns/graphql/__init__.py +7 -3
  35. netbox_dns/graphql/filters.py +16 -0
  36. netbox_dns/graphql/schema.py +20 -0
  37. netbox_dns/graphql/types.py +67 -3
  38. netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
  39. netbox_dns/locale/fr/LC_MESSAGES/django.mo +0 -0
  40. netbox_dns/migrations/0015_dnssec.py +168 -0
  41. netbox_dns/migrations/0016_dnssec_policy_status.py +18 -0
  42. netbox_dns/migrations/0017_dnssec_policy_zone_zone_template.py +41 -0
  43. netbox_dns/migrations/0018_zone_domain_status_zone_expiration_date.py +23 -0
  44. netbox_dns/models/__init__.py +2 -0
  45. netbox_dns/models/dnssec_key_template.py +114 -0
  46. netbox_dns/models/dnssec_policy.py +203 -0
  47. netbox_dns/models/record.py +1 -1
  48. netbox_dns/models/zone.py +74 -19
  49. netbox_dns/models/zone_template.py +17 -7
  50. netbox_dns/navigation.py +49 -0
  51. netbox_dns/signals/dnssec.py +32 -0
  52. netbox_dns/tables/__init__.py +2 -0
  53. netbox_dns/tables/dnssec_key_template.py +48 -0
  54. netbox_dns/tables/dnssec_policy.py +131 -0
  55. netbox_dns/tables/zone.py +23 -2
  56. netbox_dns/tables/zone_template.py +4 -0
  57. netbox_dns/template_content.py +2 -1
  58. netbox_dns/templates/netbox_dns/dnsseckeytemplate.html +70 -0
  59. netbox_dns/templates/netbox_dns/dnssecpolicy.html +155 -0
  60. netbox_dns/templates/netbox_dns/zone/registration.html +19 -0
  61. netbox_dns/templates/netbox_dns/zone.html +16 -0
  62. netbox_dns/templates/netbox_dns/zonetemplate/child.html +46 -0
  63. netbox_dns/templates/netbox_dns/zonetemplate.html +12 -0
  64. netbox_dns/urls.py +23 -0
  65. netbox_dns/utilities/conversions.py +13 -0
  66. netbox_dns/validators/__init__.py +1 -0
  67. netbox_dns/validators/dnssec.py +148 -0
  68. netbox_dns/views/__init__.py +2 -0
  69. netbox_dns/views/dnssec_key_template.py +87 -0
  70. netbox_dns/views/dnssec_policy.py +155 -0
  71. netbox_dns/views/zone.py +11 -1
  72. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7.dist-info}/METADATA +3 -2
  73. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7.dist-info}/RECORD +76 -50
  74. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7.dist-info}/WHEEL +1 -1
  75. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7.dist-info/licenses}/LICENSE +0 -0
  76. {netbox_plugin_dns-1.2.6.dist-info → netbox_plugin_dns-1.2.7.dist-info}/top_level.txt +0 -0
netbox_dns/models/zone.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import re
2
2
  from math import ceil
3
- from datetime import datetime
3
+ from datetime import datetime, date
4
4
 
5
5
  from dns import name as dns_name
6
6
  from dns.exception import DNSException
@@ -26,7 +26,12 @@ from netbox.plugins.utils import get_plugin_config
26
26
  from utilities.querysets import RestrictedQuerySet
27
27
  from ipam.models import IPAddress
28
28
 
29
- from netbox_dns.choices import RecordClassChoices, RecordTypeChoices, ZoneStatusChoices
29
+ from netbox_dns.choices import (
30
+ RecordClassChoices,
31
+ RecordTypeChoices,
32
+ ZoneStatusChoices,
33
+ ZoneEPPStatusChoices,
34
+ )
30
35
  from netbox_dns.fields import NetworkField, RFC2317NetworkField
31
36
  from netbox_dns.utilities import (
32
37
  update_dns_records,
@@ -97,6 +102,11 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
97
102
  max_length=255,
98
103
  db_collation="natural_sort",
99
104
  )
105
+ description = models.CharField(
106
+ verbose_name=_("Description"),
107
+ max_length=200,
108
+ blank=True,
109
+ )
100
110
  status = models.CharField(
101
111
  verbose_name=_("Status"),
102
112
  max_length=50,
@@ -170,25 +180,19 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
170
180
  help_text=_("Automatically generate the SOA serial number"),
171
181
  default=True,
172
182
  )
173
- description = models.CharField(
174
- verbose_name=_("Description"),
175
- max_length=200,
176
- blank=True,
177
- )
178
- arpa_network = NetworkField(
179
- verbose_name=_("ARPA Network"),
180
- help_text=_("Network related to a reverse lookup zone (.arpa)"),
181
- blank=True,
182
- null=True,
183
- )
184
- tenant = models.ForeignKey(
185
- verbose_name=_("Tenant"),
186
- to="tenancy.Tenant",
183
+ dnssec_policy = models.ForeignKey(
184
+ verbose_name=_("DNSSEC Policy"),
185
+ to="DNSSECPolicy",
187
186
  on_delete=models.PROTECT,
188
- related_name="netbox_dns_zones",
187
+ related_name="zones",
189
188
  blank=True,
190
189
  null=True,
191
190
  )
191
+ inline_signing = models.BooleanField(
192
+ verbose_name=_("Inline Signing"),
193
+ help_text=_("Use inline signing for DNSSEC"),
194
+ default=True,
195
+ )
192
196
  registrar = models.ForeignKey(
193
197
  verbose_name=_("Registrar"),
194
198
  to="Registrar",
@@ -203,6 +207,18 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
203
207
  blank=True,
204
208
  null=True,
205
209
  )
210
+ expiration_date = models.DateField(
211
+ verbose_name=_("Expiration Date"),
212
+ blank=True,
213
+ null=True,
214
+ )
215
+ domain_status = models.CharField(
216
+ verbose_name=_("Domain Status"),
217
+ max_length=50,
218
+ choices=ZoneEPPStatusChoices,
219
+ blank=True,
220
+ null=True,
221
+ )
206
222
  registrant = models.ForeignKey(
207
223
  verbose_name=_("Registrant"),
208
224
  to="RegistrationContact",
@@ -212,7 +228,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
212
228
  null=True,
213
229
  )
214
230
  admin_c = models.ForeignKey(
215
- verbose_name="Administrative Contact",
231
+ verbose_name=_("Administrative Contact"),
216
232
  to="RegistrationContact",
217
233
  on_delete=models.SET_NULL,
218
234
  related_name="admin_c_zones",
@@ -255,12 +271,27 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
255
271
  blank=True,
256
272
  null=True,
257
273
  )
274
+ arpa_network = NetworkField(
275
+ verbose_name=_("ARPA Network"),
276
+ help_text=_("Network related to a reverse lookup zone (.arpa)"),
277
+ blank=True,
278
+ null=True,
279
+ )
280
+ tenant = models.ForeignKey(
281
+ verbose_name=_("Tenant"),
282
+ to="tenancy.Tenant",
283
+ on_delete=models.PROTECT,
284
+ related_name="netbox_dns_zones",
285
+ blank=True,
286
+ null=True,
287
+ )
258
288
 
259
289
  objects = ZoneManager()
260
290
 
261
291
  clone_fields = (
262
292
  "view",
263
293
  "name",
294
+ "description",
264
295
  "status",
265
296
  "nameservers",
266
297
  "default_ttl",
@@ -271,7 +302,6 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
271
302
  "soa_retry",
272
303
  "soa_expire",
273
304
  "soa_minimum",
274
- "description",
275
305
  "tenant",
276
306
  )
277
307
 
@@ -357,6 +387,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
357
387
  def get_status_color(self):
358
388
  return ZoneStatusChoices.colors.get(self.status)
359
389
 
390
+ def get_domain_status_color(self):
391
+ return ZoneEPPStatusChoices.colors.get(self.domain_status)
392
+
360
393
  # TODO: Remove in version 1.3.0 (NetBox #18555)
361
394
  def get_absolute_url(self):
362
395
  return reverse("plugins:netbox_dns:zone", kwargs={"pk": self.pk})
@@ -397,6 +430,8 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
397
430
  self.admin_c,
398
431
  self.tech_c,
399
432
  self.billing_c,
433
+ self.expiration_date,
434
+ self.domain_status,
400
435
  )
401
436
  )
402
437
 
@@ -566,6 +601,26 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
566
601
 
567
602
  return ns_warnings, ns_errors
568
603
 
604
+ def check_expiration(self):
605
+ if self.expiration_date is None:
606
+ return None, None
607
+
608
+ expiration_warning = None
609
+ expiration_error = None
610
+
611
+ expiration_warning_days = get_plugin_config(
612
+ "netbox_dns", "zone_expiration_warning_days"
613
+ )
614
+
615
+ if self.expiration_date < date.today():
616
+ expiration_error = _("The registration for this domain has expired.")
617
+ elif (self.expiration_date - date.today()).days < expiration_warning_days:
618
+ expiration_warning = _(
619
+ f"The registration for his domain will expire less than {expiration_warning_days} days."
620
+ )
621
+
622
+ return expiration_warning, expiration_error
623
+
569
624
  def check_soa_serial_increment(self, old_serial, new_serial):
570
625
  MAX_SOA_SERIAL_INCREMENT = 2**31 - 1
571
626
  SOA_SERIAL_WRAP = 2**32
@@ -55,11 +55,11 @@ class ZoneTemplate(NetBoxModel):
55
55
  related_name="zone_templates",
56
56
  blank=True,
57
57
  )
58
- tenant = models.ForeignKey(
59
- verbose_name=_("Tenant"),
60
- to="tenancy.Tenant",
58
+ dnssec_policy = models.ForeignKey(
59
+ verbose_name=_("DNSSEC Policy"),
60
+ to="DNSSECPolicy",
61
61
  on_delete=models.SET_NULL,
62
- related_name="+",
62
+ related_name="zone_templates",
63
63
  blank=True,
64
64
  null=True,
65
65
  )
@@ -103,33 +103,43 @@ class ZoneTemplate(NetBoxModel):
103
103
  blank=True,
104
104
  null=True,
105
105
  )
106
+ tenant = models.ForeignKey(
107
+ verbose_name=_("Tenant"),
108
+ to="tenancy.Tenant",
109
+ on_delete=models.SET_NULL,
110
+ related_name="+",
111
+ blank=True,
112
+ null=True,
113
+ )
106
114
 
107
115
  clone_fields = (
108
116
  "description",
109
117
  "nameservers",
110
118
  "record_templates",
111
- "tenant",
119
+ "dnssec_policy",
112
120
  "registrar",
113
121
  "registrant",
114
122
  "admin_c",
115
123
  "tech_c",
116
124
  "billing_c",
125
+ "tenant",
117
126
  )
118
127
 
119
128
  template_fields = (
120
129
  "soa_mname",
121
130
  "soa_rname",
122
- "tenant",
131
+ "dnssec_policy",
123
132
  "registrar",
124
133
  "registrant",
125
134
  "admin_c",
126
135
  "tech_c",
127
136
  "billing_c",
137
+ "tenant",
128
138
  )
129
139
 
130
140
  class Meta:
131
141
  verbose_name = _("Zone Template")
132
- verbose_name_plural = "Zone Templates"
142
+ verbose_name_plural = _("Zone Templates")
133
143
 
134
144
  ordering = ("name",)
135
145
 
netbox_dns/navigation.py CHANGED
@@ -92,6 +92,46 @@ managed_record_menu_item = PluginMenuItem(
92
92
  permissions=["netbox_dns.view_record"],
93
93
  )
94
94
 
95
+ dnsseckeytemplate_menu_item = PluginMenuItem(
96
+ link="plugins:netbox_dns:dnsseckeytemplate_list",
97
+ link_text=_("DNSSEC Key Templates"),
98
+ permissions=["netbox_dns.view_dnsseckeytemplate"],
99
+ buttons=(
100
+ PluginMenuButton(
101
+ "plugins:netbox_dns:dnsseckeytemplate_add",
102
+ _("Add"),
103
+ "mdi mdi-plus-thick",
104
+ permissions=["netbox_dns.add_dnsseckeytemplate"],
105
+ ),
106
+ PluginMenuButton(
107
+ "plugins:netbox_dns:dnsseckeytemplate_bulk_import",
108
+ _("Import"),
109
+ "mdi mdi-upload",
110
+ permissions=["netbox_dns.add_dnsseckeytemplate"],
111
+ ),
112
+ ),
113
+ )
114
+
115
+ dnssecpolicy_menu_item = PluginMenuItem(
116
+ link="plugins:netbox_dns:dnssecpolicy_list",
117
+ link_text=_("DNSSEC Policies"),
118
+ permissions=["netbox_dns.view_dnssecpolicy"],
119
+ buttons=(
120
+ PluginMenuButton(
121
+ "plugins:netbox_dns:dnssecpolicy_add",
122
+ _("Add"),
123
+ "mdi mdi-plus-thick",
124
+ permissions=["netbox_dns.add_dnssecpolicy"],
125
+ ),
126
+ PluginMenuButton(
127
+ "plugins:netbox_dns:dnssecpolicy_bulk_import",
128
+ _("Import"),
129
+ "mdi mdi-upload",
130
+ permissions=["netbox_dns.add_dnssecpolicy"],
131
+ ),
132
+ ),
133
+ )
134
+
95
135
  zonetemplate_menu_item = PluginMenuItem(
96
136
  link="plugins:netbox_dns:zonetemplate_list",
97
137
  link_text=_("Zone Templates"),
@@ -187,6 +227,13 @@ if top_level_menu:
187
227
  managed_record_menu_item,
188
228
  ),
189
229
  ),
230
+ (
231
+ _("DNSSEC"),
232
+ (
233
+ dnsseckeytemplate_menu_item,
234
+ dnssecpolicy_menu_item,
235
+ ),
236
+ ),
190
237
  (
191
238
  _("Templates"),
192
239
  (
@@ -211,6 +258,8 @@ else:
211
258
  nameserver_menu_item,
212
259
  record_menu_item,
213
260
  managed_record_menu_item,
261
+ dnsseckeytemplate_menu_item,
262
+ dnssecpolicy_menu_item,
214
263
  registrar_menu_item,
215
264
  contact_menu_item,
216
265
  )
@@ -0,0 +1,32 @@
1
+ from django.dispatch import receiver
2
+ from django.db.models.signals import m2m_changed
3
+ from django.core.exceptions import ValidationError
4
+
5
+ from netbox.context import current_request
6
+ from utilities.exceptions import AbortRequest
7
+
8
+ from netbox_dns.validators import validate_key_template_assignment
9
+
10
+ from netbox_dns.models import DNSSECPolicy, DNSSECKeyTemplate
11
+
12
+
13
+ @receiver(m2m_changed, sender=DNSSECPolicy.key_templates.through)
14
+ def dnssec_policy_key_templates_changed(action, instance, pk_set, **kwargs):
15
+ request = current_request.get()
16
+
17
+ key_templates = instance.key_templates.all()
18
+ match action:
19
+ case "pre_remove":
20
+ key_templates = key_templates.exclude(pk__in=pk_set)
21
+ case "pre_add":
22
+ key_templates |= DNSSECKeyTemplate.objects.filter(pk__in=pk_set)
23
+ case _:
24
+ return
25
+
26
+ try:
27
+ validate_key_template_assignment(key_templates)
28
+ except ValidationError as exc:
29
+ if request is not None:
30
+ raise AbortRequest(exc)
31
+ else:
32
+ raise exc
@@ -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,48 @@
1
+ import django_tables2 as tables
2
+ from django.utils.translation import gettext_lazy as _
3
+
4
+
5
+ from netbox.tables import (
6
+ NetBoxTable,
7
+ ChoiceFieldColumn,
8
+ TagColumn,
9
+ )
10
+ from tenancy.tables import TenancyColumnsMixin
11
+
12
+ from netbox_dns.models import DNSSECKeyTemplate
13
+
14
+
15
+ __all__ = ("DNSSECKeyTemplateTable",)
16
+
17
+
18
+ class DNSSECKeyTemplateTable(TenancyColumnsMixin, NetBoxTable):
19
+ name = tables.Column(
20
+ verbose_name=_("Name"),
21
+ linkify=True,
22
+ )
23
+ type = ChoiceFieldColumn(
24
+ verbose_name=_("Key Type"),
25
+ )
26
+ lifetime = tables.Column(
27
+ verbose_name=_("Lifetime"),
28
+ )
29
+ algorithm = ChoiceFieldColumn(
30
+ verbose_name=_("Algorithm"),
31
+ )
32
+ key_size = ChoiceFieldColumn(
33
+ verbose_name=_("Key Size"),
34
+ )
35
+ tags = TagColumn(
36
+ url_name="plugins:netbox_dns:dnsseckeytemplate_list",
37
+ )
38
+
39
+ class Meta(NetBoxTable.Meta):
40
+ model = DNSSECKeyTemplate
41
+ fields = ("description",)
42
+ default_columns = (
43
+ "name",
44
+ "type",
45
+ "algorithm",
46
+ "key_size",
47
+ "tags",
48
+ )
@@ -0,0 +1,131 @@
1
+ import django_tables2 as tables
2
+ from django.utils.translation import gettext_lazy as _
3
+
4
+
5
+ from netbox.tables import (
6
+ NetBoxTable,
7
+ TagColumn,
8
+ ChoiceFieldColumn,
9
+ ActionsColumn,
10
+ )
11
+ from tenancy.tables import TenancyColumnsMixin
12
+
13
+ from netbox_dns.models import DNSSECPolicy
14
+
15
+
16
+ __all__ = (
17
+ "DNSSECPolicyTable",
18
+ "DNSSECPolicyDisplayTable",
19
+ )
20
+
21
+
22
+ class DNSSECPolicyTable(TenancyColumnsMixin, NetBoxTable):
23
+ name = tables.Column(
24
+ verbose_name=_("Name"),
25
+ linkify=True,
26
+ )
27
+ status = ChoiceFieldColumn(
28
+ verbose_name=_("Status"),
29
+ )
30
+ dnskey_ttl = tables.Column(
31
+ verbose_name=_("DNSKEY TTL"),
32
+ )
33
+ purge_keys = tables.Column(
34
+ verbose_name=_("Purge Keys"),
35
+ )
36
+ publish_safety = tables.Column(
37
+ verbose_name=_("Publish Safety"),
38
+ )
39
+ retire_safety = tables.Column(
40
+ verbose_name=_("Retire Safety"),
41
+ )
42
+ signatures_jitter = tables.Column(
43
+ verbose_name=_("Signatures Jitter"),
44
+ )
45
+ signatures_refresh = tables.Column(
46
+ verbose_name=_("Signatures Refresh"),
47
+ )
48
+ signatures_validity = tables.Column(
49
+ verbose_name=_("Signatures Validity"),
50
+ )
51
+ signatures_validity_dnskey = tables.Column(
52
+ verbose_name=_("Signatures Validity (DNSKEY)"),
53
+ )
54
+ max_zone_ttl = tables.Column(
55
+ verbose_name=_("Max Zone TTL"),
56
+ )
57
+ dnskey_ttl = tables.Column(
58
+ verbose_name=_("DNSKEY TTL"),
59
+ )
60
+ zone_propagation_delay = tables.Column(
61
+ verbose_name=_("Zone Propagation Delay"),
62
+ )
63
+ create_cdnskey = tables.BooleanColumn(
64
+ verbose_name=_("Create CDNSKEY"),
65
+ )
66
+ cds_digest_types = tables.Column(
67
+ verbose_name=_("CDS Digest Types"),
68
+ )
69
+ parent_ds_ttl = tables.Column(
70
+ verbose_name=_("Parent DS TTL"),
71
+ )
72
+ parent_propagation_delay = tables.Column(
73
+ verbose_name=_("Parent Propagation Delay"),
74
+ )
75
+ use_nsec3 = tables.BooleanColumn(
76
+ verbose_name=_("Use NSEC3"),
77
+ )
78
+ nsec3_iterations = tables.Column(
79
+ verbose_name=_("NSEC3 Iterations"),
80
+ )
81
+ nsec3_opt_out = tables.BooleanColumn(
82
+ verbose_name=_("NSEC3 Opt Out"),
83
+ )
84
+ nsec3_salt_size = tables.Column(
85
+ verbose_name=_("NSEC3 Salt Size"),
86
+ )
87
+ tags = TagColumn(
88
+ url_name="plugins:netbox_dns:dnssecpolicy_list",
89
+ )
90
+
91
+ class Meta(NetBoxTable.Meta):
92
+ model = DNSSECPolicy
93
+ fields = ("description",)
94
+ default_columns = (
95
+ "name",
96
+ "description",
97
+ "status",
98
+ "use_nsec3",
99
+ "tags",
100
+ )
101
+
102
+
103
+ class DNSSECPolicyDisplayTable(TenancyColumnsMixin, NetBoxTable):
104
+ actions = ActionsColumn(actions="")
105
+
106
+ name = tables.Column(
107
+ verbose_name=_("Name"),
108
+ linkify=True,
109
+ )
110
+ status = ChoiceFieldColumn(
111
+ verbose_name=_("Status"),
112
+ )
113
+ create_cdnskey = tables.BooleanColumn(
114
+ verbose_name=_("Create CDNSKEY"),
115
+ )
116
+ use_nsec3 = tables.BooleanColumn(
117
+ verbose_name=_("Use NSEC3"),
118
+ )
119
+ tags = TagColumn(
120
+ url_name="plugins:netbox_dns:dnssecpolicy_list",
121
+ )
122
+
123
+ class Meta(NetBoxTable.Meta):
124
+ model = DNSSECPolicy
125
+ fields = ("description",)
126
+ default_columns = (
127
+ "name",
128
+ "description",
129
+ "status",
130
+ "tags",
131
+ )
netbox_dns/tables/zone.py CHANGED
@@ -5,13 +5,17 @@ from netbox.tables import (
5
5
  ChoiceFieldColumn,
6
6
  NetBoxTable,
7
7
  TagColumn,
8
+ ActionsColumn,
8
9
  )
9
10
  from tenancy.tables import TenancyColumnsMixin
10
11
 
11
12
  from netbox_dns.models import Zone
12
13
 
13
14
 
14
- __all__ = ("ZoneTable",)
15
+ __all__ = (
16
+ "ZoneTable",
17
+ "ZoneDisplayTable",
18
+ )
15
19
 
16
20
 
17
21
  class ZoneTable(TenancyColumnsMixin, NetBoxTable):
@@ -34,7 +38,11 @@ class ZoneTable(TenancyColumnsMixin, NetBoxTable):
34
38
  url_name="plugins:netbox_dns:zone_list",
35
39
  )
36
40
  default_ttl = tables.Column(
37
- verbose_name="Default TTL",
41
+ verbose_name=_("Default TTL"),
42
+ )
43
+ dnssec_policy = tables.Column(
44
+ verbose_name=_("DNSSEC Policy"),
45
+ linkify=True,
38
46
  )
39
47
  rfc2317_prefix = tables.Column(
40
48
  verbose_name=_("RFC2317 Prefix"),
@@ -47,6 +55,9 @@ class ZoneTable(TenancyColumnsMixin, NetBoxTable):
47
55
  verbose_name=_("Registrar"),
48
56
  linkify=True,
49
57
  )
58
+ domain_status = ChoiceFieldColumn(
59
+ verbose_name=_("Domain Status"),
60
+ )
50
61
  registrant = tables.Column(
51
62
  verbose_name=_("Registrant"),
52
63
  linkify=True,
@@ -73,8 +84,11 @@ class ZoneTable(TenancyColumnsMixin, NetBoxTable):
73
84
  "description",
74
85
  "soa_rname",
75
86
  "soa_serial",
87
+ "inline_signing",
76
88
  "rfc2317_parent_managed",
77
89
  "registry_domain_id",
90
+ "expiration_date",
91
+ "domain_status",
78
92
  )
79
93
  default_columns = (
80
94
  "name",
@@ -82,3 +96,10 @@ class ZoneTable(TenancyColumnsMixin, NetBoxTable):
82
96
  "status",
83
97
  "tags",
84
98
  )
99
+
100
+
101
+ class ZoneDisplayTable(ZoneTable):
102
+ actions = ActionsColumn(actions=("changelog",))
103
+
104
+ class Meta(ZoneTable.Meta):
105
+ pass
@@ -25,6 +25,10 @@ class ZoneTemplateTable(TenancyColumnsMixin, NetBoxTable):
25
25
  tags = TagColumn(
26
26
  url_name="plugins:netbox_dns:zonetemplate_list",
27
27
  )
28
+ dnssec_policy = tables.Column(
29
+ verbose_name=_("DNSSEC Policy"),
30
+ linkify=True,
31
+ )
28
32
  registrar = tables.Column(
29
33
  verbose_name=_("Registrar"),
30
34
  linkify=True,
@@ -2,6 +2,7 @@ import django_tables2 as tables
2
2
 
3
3
  from django.conf import settings
4
4
  from django.urls import reverse
5
+ from django.utils.translation import gettext_lazy as _
5
6
 
6
7
  from netbox.plugins.utils import get_plugin_config
7
8
  from netbox.plugins import PluginTemplateExtension
@@ -119,7 +120,7 @@ class IPRelatedDNSRecords(PluginTemplateExtension):
119
120
 
120
121
 
121
122
  address_records = tables.ManyToManyColumn(
122
- verbose_name="DNS Address Records",
123
+ verbose_name=_("DNS Address Records"),
123
124
  accessor="netbox_dns_records",
124
125
  linkify_item=True,
125
126
  transform=lambda obj: (
@@ -0,0 +1,70 @@
1
+ {% extends 'generic/object.html' %}
2
+ {% load render_table from django_tables2 %}
3
+ {% load i18n %}
4
+
5
+ {% block content %}
6
+ <div class="row">
7
+ <div class="col col-md-6">
8
+ <div class="card">
9
+ <h5 class="card-header">{% trans "DNSSEC Key" %}</h5>
10
+ <table class="table table-hover attr-table">
11
+ <tr>
12
+ <th scope="row">{% trans "Name" %}</th>
13
+ <td>{{ object.name }}</td>
14
+ </tr>
15
+ {% if object.description %}
16
+ <tr>
17
+ <th scope="row">{% trans "Description" %}</th>
18
+ <td style="word-break:break-all;">{{ object.description }}</td>
19
+ </tr>
20
+ {% endif %}
21
+ <tr>
22
+ <th scope="row">{% trans "Type" %}</th>
23
+ <td>{% badge object.get_type_display bg_color=object.get_type_color %}</td>
24
+ </tr>
25
+ <tr>
26
+ <th scope="row">{% trans "Lifetime" %}</th>
27
+ <td>{{ object.lifetime|placeholder }}</td>
28
+ </tr>
29
+ <tr>
30
+ <th scope="row">{% trans "Algorithm" %}</th>
31
+ <td>{% badge object.get_algorithm_display %}</td>
32
+ </tr>
33
+ <tr>
34
+ <th scope="row">{% trans "Key Size" %}</th>
35
+ <td>{% badge object.get_key_size_display %}</td>
36
+ </tr>
37
+ {% if object.tenant %}
38
+ <tr>
39
+ <th scope="row">{% trans "Tenant" %}</th>
40
+ <td>
41
+ {% if object.tenant.group %}
42
+ {{ object.tenant.group|linkify }} /
43
+ {% endif %}
44
+ {{ object.tenant|linkify|placeholder }}
45
+ </td>
46
+ </tr>
47
+ {% endif %}
48
+ </table>
49
+ </div>
50
+ {% include 'inc/panels/custom_fields.html' %}
51
+ </div>
52
+ <div class="col col-md-6">
53
+ {% include 'inc/panels/tags.html' %}
54
+ </div>
55
+ </div>
56
+ {% if policy_table %}
57
+ <div class="col col-md-12">
58
+ <div class="card">
59
+ {% if policy_table.rows|length == 1 %}
60
+ <h2 class="card-header">{% trans "Policy" %}</h2>
61
+ {% else %}
62
+ <h2 class="card-header">{% trans "Policies" %}</h2>
63
+ {% endif %}
64
+ <div class="table-responsive">
65
+ {% render_table policy_table 'inc/table.html' %}
66
+ </div>
67
+ </div>
68
+ </div>
69
+ {% endif %}
70
+ {% endblock %}