From 4cb6abfc18cbfbe903775881f24fa1f7415a3d1e Mon Sep 17 00:00:00 2001 From: Alexander Haase Date: Sat, 30 Nov 2024 16:48:44 +0100 Subject: [PATCH 1/2] Hide traceback from rendered device config When an exception occurs during device configuration rendering, it usually doesn't contain information about the template being rendered, but rather the trace of how the template was rendered. Since this could confuse users and expose internal server information, it is now hidden. --- netbox/dcim/views.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index f390be89bb0..79b7936b20c 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -1,5 +1,3 @@ -import traceback - from django.contrib import messages from django.contrib.contenttypes.models import ContentType from django.core.paginator import EmptyPage, PageNotAnInteger @@ -2128,8 +2126,9 @@ def get_extra_context(self, request, instance): try: rendered_config = config_template.render(context=context_data) except TemplateError as e: - messages.error(request, _("An error occurred while rendering the template: {error}").format(error=e)) - rendered_config = traceback.format_exc() + msg = _("An error occurred while rendering the template: {error}").format(error=e) + messages.error(request, msg) + rendered_config = msg return { 'config_template': config_template, From c2d429f4d82a07094d8ce33b8eb2c30e62fe4889 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 11 Dec 2024 09:59:54 -0500 Subject: [PATCH 2/2] Improve error message display; replicate changes for VMs --- netbox/dcim/views.py | 9 ++--- .../templates/dcim/device/render_config.html | 33 ++++++++++++------- .../virtualmachine/render_config.html | 33 ++++++++++++------- netbox/virtualization/views.py | 10 +++--- 4 files changed, 52 insertions(+), 33 deletions(-) diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 79b7936b20c..c8474b01dff 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -2104,7 +2104,8 @@ def get(self, request, **kwargs): # If a direct export has been requested, return the rendered template content as a # downloadable file. if request.GET.get('export'): - response = HttpResponse(context['rendered_config'], content_type='text') + content = context['rendered_config'] or context['error_message'] + response = HttpResponse(content, content_type='text') filename = f"{instance.name or 'config'}.txt" response['Content-Disposition'] = f'attachment; filename="{filename}"' return response @@ -2122,18 +2123,18 @@ def get_extra_context(self, request, instance): # Render the config template rendered_config = None + error_message = None if config_template := instance.get_config_template(): try: rendered_config = config_template.render(context=context_data) except TemplateError as e: - msg = _("An error occurred while rendering the template: {error}").format(error=e) - messages.error(request, msg) - rendered_config = msg + error_message = _("An error occurred while rendering the template: {error}").format(error=e) return { 'config_template': config_template, 'context_data': context_data, 'rendered_config': rendered_config, + 'error_message': error_message, } diff --git a/netbox/templates/dcim/device/render_config.html b/netbox/templates/dcim/device/render_config.html index 785939a834b..ab2f1c531d2 100644 --- a/netbox/templates/dcim/device/render_config.html +++ b/netbox/templates/dcim/device/render_config.html @@ -5,7 +5,7 @@ {% block title %}{{ object }} - {% trans "Config" %}{% endblock %} {% block content %} -
+

{% trans "Config Template" %}

@@ -48,19 +48,28 @@

-
-

- {% trans "Rendered Config" %} - - {% trans "Download" %} - -

- {% if config_template %} -
{{ rendered_config }}
+ {% if config_template %} + {% if rendered_config %} +
+

+ {% trans "Rendered Config" %} + + {% trans "Download" %} + +

+
{{ rendered_config }}
+
{% else %} -
{% trans "No configuration template found" %}
+
+

{% trans "Error rendering template" %}

+ {% trans error_message %} +
{% endif %} -
+ {% else %} +
+ {% trans "No configuration template has been assigned for this device." %} +
+ {% endif %}
{% endblock %} diff --git a/netbox/templates/virtualization/virtualmachine/render_config.html b/netbox/templates/virtualization/virtualmachine/render_config.html index 5e7a0711bf2..fa6f1723b7b 100644 --- a/netbox/templates/virtualization/virtualmachine/render_config.html +++ b/netbox/templates/virtualization/virtualmachine/render_config.html @@ -5,7 +5,7 @@ {% block title %}{{ object }} - {% trans "Config" %}{% endblock %} {% block content %} -
+

{% trans "Config Template" %}

@@ -48,19 +48,28 @@

-
-

- {% trans "Rendered Config" %} - - {% trans "Download" %} - -

- {% if config_template %} -
{{ rendered_config }}
+ {% if config_template %} + {% if rendered_config %} +
+

+ {% trans "Rendered Config" %} + + {% trans "Download" %} + +

+
{{ rendered_config }}
+
{% else %} -
{% trans "No configuration template found" %}
+
+

{% trans "Error rendering template" %}

+ {% trans error_message %} +
{% endif %} -
+ {% else %} +
+ {% trans "No configuration template has been assigned for this virtual machine." %} +
+ {% endif %}
{% endblock %} diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index d1d65b1ffb0..f71d56b19b8 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -1,5 +1,3 @@ -import traceback - from django.contrib import messages from django.db import transaction from django.db.models import Prefetch, Sum @@ -425,7 +423,8 @@ def get(self, request, **kwargs): # If a direct export has been requested, return the rendered template content as a # downloadable file. if request.GET.get('export'): - response = HttpResponse(context['rendered_config'], content_type='text') + content = context['rendered_config'] or context['error_message'] + response = HttpResponse(content, content_type='text') filename = f"{instance.name or 'config'}.txt" response['Content-Disposition'] = f'attachment; filename="{filename}"' return response @@ -443,17 +442,18 @@ def get_extra_context(self, request, instance): # Render the config template rendered_config = None + error_message = None if config_template := instance.get_config_template(): try: rendered_config = config_template.render(context=context_data) except TemplateError as e: - messages.error(request, _("An error occurred while rendering the template: {error}").format(error=e)) - rendered_config = traceback.format_exc() + error_message = _("An error occurred while rendering the template: {error}").format(error=e) return { 'config_template': config_template, 'context_data': context_data, 'rendered_config': rendered_config, + 'error_message': error_message, }