diff --git a/puppetboard/core.py b/puppetboard/core.py index 4d43b7d0..ea8c8f7b 100644 --- a/puppetboard/core.py +++ b/puppetboard/core.py @@ -6,6 +6,7 @@ from flask import Flask from flask_caching import Cache from flask_apscheduler import APScheduler +from markupsafe import escape from pypuppetdb import connect from puppetboard.utils import (get_or_abort, jsonprint, @@ -247,3 +248,20 @@ def to_html(message: str) -> str: r"(file: \1, line: \2)", message) return message + + +def get_error_html(node_name, source, message, show_error_as): + + # sanitize the data from PuppetDB first, + # as we will add some HTML tags in the functions below and don't want these + # to be escaped + safe_source = escape(source) + safe_message = escape(message) + + # enrich the message using HTML + if show_error_as == 'friendly': + error_html = to_html(get_friendly_error(safe_source, safe_message, node_name)) + else: + error_html = get_raw_error(safe_source, safe_message) + + return error_html diff --git a/puppetboard/templates/report.html b/puppetboard/templates/report.html index f2ca19d2..3df36640 100644 --- a/puppetboard/templates/report.html +++ b/puppetboard/templates/report.html @@ -108,9 +108,9 @@

Metrics

} }, { data: 'level', name: 'level' }, - { data: 'source', name: 'source', visible: false }, + { data: 'source', name: 'source', visible: false, render: DataTable.render.text() }, { data: 'tags', name: 'tags', visible: false }, - { data: 'message', name: 'message' }, + { data: 'message', name: 'message' }, // HTML for this column is sanitized in get_message() // see also the comment about these columns in reports.py { data: 'location', name: 'location', visible: false }, { data: 'short_location', name: 'short_location' }, @@ -176,10 +176,10 @@

Metrics

"data": events, 'columns': [ - { data: 'resource' }, + { data: 'resource', render: DataTable.render.text() }, { data: 'status' }, - { data: 'old' }, - { data: 'new' }, + { data: 'old', render: DataTable.render.text() }, + { data: 'new', render: DataTable.render.text() }, ], "ordering": false, diff --git a/puppetboard/views/failures.py b/puppetboard/views/failures.py index d31c7b79..63dd4ace 100644 --- a/puppetboard/views/failures.py +++ b/puppetboard/views/failures.py @@ -1,8 +1,8 @@ from flask import Response, stream_with_context, abort from pypuppetdb.QueryBuilder import AndOperator, EqualsOperator -from puppetboard.core import get_app, get_puppetdb, environments, stream_template, to_html, \ - get_friendly_error, get_raw_error +from puppetboard.core import get_app, get_puppetdb, environments, \ + stream_template, get_error_html from puppetboard.utils import check_env, yield_or_stop app = get_app() @@ -55,12 +55,9 @@ def failures(env: str, show_error_as: str): break if source and message: - if show_error_as == 'friendly': - error = to_html(get_friendly_error(source, message, node.name)) - else: - error = get_raw_error(source, message) + error = get_error_html(node.name, source, message, show_error_as) else: - error = to_html(f'Node {node.name} is failing but we could not find the errors') + error = f'Node {node.name} is failing but we could not find the errors' failure = { 'certname': node.name, diff --git a/puppetboard/views/reports.py b/puppetboard/views/reports.py index 47dd6d94..05e56733 100644 --- a/puppetboard/views/reports.py +++ b/puppetboard/views/reports.py @@ -10,8 +10,8 @@ EqualsOperator, OrOperator, LessEqualOperator, RegexOperator, GreaterEqualOperator) -from puppetboard.core import get_app, get_puppetdb, environments, REPORTS_COLUMNS, to_html, \ - get_raw_error, get_friendly_error +from puppetboard.core import get_app, get_puppetdb, environments, \ + REPORTS_COLUMNS, get_error_html from puppetboard.utils import (check_env, get_or_abort) app = get_app() @@ -179,12 +179,6 @@ def get_short_location(location: str) -> str: return location -def get_message(node_name, log, show_error_as): - if show_error_as == 'friendly': - error = to_html(get_friendly_error(log['source'], log['message'], node_name)) - else: - error = get_raw_error(log['source'], log['message']) - return error @app.route('/report//', @@ -254,7 +248,7 @@ def report(env, node_name, report_id, show_error_as): 'level': log["level"], 'source': log['source'], 'tags': ', '.join(log['tags']), - 'message': get_message(node_name, log, show_error_as), + 'message': get_error_html(node_name, log['source'], log['message'], show_error_as), 'location': get_location(log), # this could be also done with a different rendered in DataTables, # - feel free to refactor it into that if you know how