From 2b3e22a597cffd02054cc7c8f5129611503a2e1b Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 11 Dec 2024 14:58:41 +0000 Subject: [PATCH 01/17] install jinja2 --- modules/test/base/python/requirements.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/test/base/python/requirements.txt b/modules/test/base/python/requirements.txt index 0ed8a792d..5d12be720 100644 --- a/modules/test/base/python/requirements.txt +++ b/modules/test/base/python/requirements.txt @@ -6,4 +6,7 @@ protobuf==5.28.0 # User defined packages grpcio==1.67.1 grpcio-tools==1.67.1 -netifaces==0.11.0 \ No newline at end of file +netifaces==0.11.0 + +# Requirements for reports generation +Jinja2==3.1.4 \ No newline at end of file From 337552f7b18d6235a2f3898d39b02eb1074dab45 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 11 Dec 2024 15:08:20 +0000 Subject: [PATCH 02/17] base module template --- modules/test/base/base.Dockerfile | 8 +++++++ modules/test/base/python/src/test_module.py | 2 ++ resources/report/module_report_base.jinja2 | 24 +++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 resources/report/module_report_base.jinja2 diff --git a/modules/test/base/base.Dockerfile b/modules/test/base/base.Dockerfile index 253270ea9..7a82301a7 100644 --- a/modules/test/base/base.Dockerfile +++ b/modules/test/base/base.Dockerfile @@ -80,5 +80,13 @@ COPY --from=builder /usr/local/etc/oui.txt /usr/local/etc/oui.txt # Activate the virtual environment by setting the PATH ENV PATH="/opt/venv/bin:$PATH" +# Common resource folder +ENV REPORT_TEMPLATE_PATH=/testrun/resources +# Jinja base template +ENV BASE_TEMPLATE_FILE=module_report_base.jinja2 + +# Copy base template +COPY resources/report/$BASE_TEMPLATE_FILE $REPORT_TEMPLATE_PATH/ + # Start the test module ENTRYPOINT [ "/testrun/bin/start" ] \ No newline at end of file diff --git a/modules/test/base/python/src/test_module.py b/modules/test/base/python/src/test_module.py index 21de78143..73187d789 100644 --- a/modules/test/base/python/src/test_module.py +++ b/modules/test/base/python/src/test_module.py @@ -42,6 +42,8 @@ def __init__(self, self._ipv6_subnet = os.environ.get('IPV6_SUBNET', '') self._dev_iface_mac = os.environ.get('DEV_IFACE_MAC', '') self._device_test_pack = json.loads(os.environ.get('DEVICE_TEST_PACK', '')) + self._report_template_folder = os.environ.get('REPORT_TEMPLATE_PATH') + self._base_template_file=os.environ.get('BASE_TEMPLATE_FILE') self._add_logger(log_name=log_name) self._config = self._read_config( conf_file=conf_file if conf_file is not None else CONF_FILE) diff --git a/resources/report/module_report_base.jinja2 b/resources/report/module_report_base.jinja2 new file mode 100644 index 000000000..4edc56e0b --- /dev/null +++ b/resources/report/module_report_base.jinja2 @@ -0,0 +1,24 @@ +
+ {% if module_header %} +

{{ module_header }}

+ + {% else %} +
+ {% endif %} + + + {% for header in summary_headers %} + + {% endfor %} + + + + + {% for cell in summary_data %} + + {% endfor %} + + +
{{ header }}
{{ cell }}
+ {% block content %}{% endblock content %} +
\ No newline at end of file From 0e0c950f7ed98e2e0c118e9b603c33d60320f2f7 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 11 Dec 2024 17:42:08 +0000 Subject: [PATCH 03/17] ntp module template --- modules/test/ntp/ntp.Dockerfile | 5 +++- modules/test/ntp/python/src/ntp_module.py | 24 +++++++++++++++++-- .../test/ntp/resources/report_template.jinja2 | 2 ++ 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 modules/test/ntp/resources/report_template.jinja2 diff --git a/modules/test/ntp/ntp.Dockerfile b/modules/test/ntp/ntp.Dockerfile index 4d9701464..c7ae7fee1 100644 --- a/modules/test/ntp/ntp.Dockerfile +++ b/modules/test/ntp/ntp.Dockerfile @@ -31,4 +31,7 @@ COPY $MODULE_DIR/conf /testrun/conf COPY $MODULE_DIR/bin /testrun/bin # Copy over all python files -COPY $MODULE_DIR/python /testrun/python \ No newline at end of file +COPY $MODULE_DIR/python /testrun/python + +# Copy Jinja template +COPY $MODULE_DIR/resources/report_template.jinja2 $REPORT_TEMPLATE_PATH/ \ No newline at end of file diff --git a/modules/test/ntp/python/src/ntp_module.py b/modules/test/ntp/python/src/ntp_module.py index 22fbf40ed..bf64c5891 100644 --- a/modules/test/ntp/python/src/ntp_module.py +++ b/modules/test/ntp/python/src/ntp_module.py @@ -16,6 +16,7 @@ from scapy.all import rdpcap, IP, IPv6, NTP, UDP, Ether import os from collections import defaultdict +from jinja2 import Environment, FileSystemLoader LOG_NAME = 'test_ntp' MODULE_REPORT_FILE_NAME = 'ntp_report.html' @@ -23,6 +24,7 @@ STARTUP_CAPTURE_FILE = '/runtime/device/startup.pcap' MONITOR_CAPTURE_FILE = '/runtime/device/monitor.pcap' LOGGER = None +REPORT_TEMPLATE_FILE = 'report_template.jinja2' class NTPModule(TestModule): @@ -49,11 +51,20 @@ def __init__(self, LOGGER = self._get_logger() def generate_module_report(self): + # Load Jinja2 template + loader=FileSystemLoader(self._report_template_folder) + template = Environment(loader=loader).get_template(REPORT_TEMPLATE_FILE) + module_header="NTP Module" + summmary_headers = [ + 'Requests to local NTP server', + 'Requests to external NTP servers', + 'Total NTP requests', + 'Total NTP responses' + ] + # Extract NTP data from the pcap file ntp_table_data = self.extract_ntp_data() - html_content = '

NTP Module

' - # Set the summary variables local_requests = sum( 1 for row in ntp_table_data @@ -67,6 +78,15 @@ def generate_module_report(self): total_responses = sum(1 for row in ntp_table_data if row['Type'] == 'Server') + summary_data = [ + local_requests, + external_requests, + total_requests, + total_responses + ] + + html_content = '

NTP Module

' + # Initialize a dictionary to store timestamps for each unique combination timestamps = defaultdict(list) diff --git a/modules/test/ntp/resources/report_template.jinja2 b/modules/test/ntp/resources/report_template.jinja2 new file mode 100644 index 000000000..793b65df2 --- /dev/null +++ b/modules/test/ntp/resources/report_template.jinja2 @@ -0,0 +1,2 @@ +{% extends base_template %} +{% block content %}{% endblock %} \ No newline at end of file From 99fa744311a68476f559652550505cb34e8b6d50 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Fri, 13 Dec 2024 18:56:22 +0100 Subject: [PATCH 04/17] add page header and footer to the base_template --- resources/report/module_report_base.jinja2 | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/resources/report/module_report_base.jinja2 b/resources/report/module_report_base.jinja2 index 4edc56e0b..009b7646d 100644 --- a/resources/report/module_report_base.jinja2 +++ b/resources/report/module_report_base.jinja2 @@ -1,3 +1,26 @@ +{% raw %} +
+
+
+ {# Badge #} +

+ {% if json_data['device']['test_pack'] == 'Device Qualification' %} + + Device Qualification + {% else %} + + Pilot Assessment + {% endif %} +

+ {{ title }} +
+ + {{ device['manufacturer'] }} + {{ device['model']}} + + Testrun +
+{% endraw %}
{% if module_header %}

{{ module_header }}

@@ -21,4 +44,12 @@ {% block content %}{% endblock content %} -
\ No newline at end of file +
+{% raw %} + + +
+{% endraw %} \ No newline at end of file From 9c100eed0580feb6d4e8a5a4b33cb3d15b0b7ccf Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Fri, 13 Dec 2024 19:00:48 +0100 Subject: [PATCH 05/17] generate ntp module report using Jinja --- modules/test/ntp/python/src/ntp_module.py | 119 ++++++++---------- .../test/ntp/resources/report_template.jinja2 | 31 ++++- 2 files changed, 83 insertions(+), 67 deletions(-) diff --git a/modules/test/ntp/python/src/ntp_module.py b/modules/test/ntp/python/src/ntp_module.py index bf64c5891..411776899 100644 --- a/modules/test/ntp/python/src/ntp_module.py +++ b/modules/test/ntp/python/src/ntp_module.py @@ -19,7 +19,7 @@ from jinja2 import Environment, FileSystemLoader LOG_NAME = 'test_ntp' -MODULE_REPORT_FILE_NAME = 'ntp_report.html' +MODULE_REPORT_FILE_NAME = 'ntp_report.jinja2' NTP_SERVER_CAPTURE_FILE = '/runtime/network/ntp.pcap' STARTUP_CAPTURE_FILE = '/runtime/device/startup.pcap' MONITOR_CAPTURE_FILE = '/runtime/device/monitor.pcap' @@ -52,16 +52,30 @@ def __init__(self, def generate_module_report(self): # Load Jinja2 template + page_max_height = 910 + header_height = 48 + summary_height = 135 + row_height = 42 loader=FileSystemLoader(self._report_template_folder) template = Environment(loader=loader).get_template(REPORT_TEMPLATE_FILE) - module_header="NTP Module" - summmary_headers = [ + module_header='NTP Module' + # Summary table headers + summary_headers = [ 'Requests to local NTP server', 'Requests to external NTP servers', 'Total NTP requests', 'Total NTP responses' ] - + # Module data Headers + module_data_headers = [ + 'Source', + 'Destination', + 'Type', + 'Version', + 'Count', + 'Sync Request Average', + ] + # Extract NTP data from the pcap file ntp_table_data = self.extract_ntp_data() @@ -78,14 +92,13 @@ def generate_module_report(self): total_responses = sum(1 for row in ntp_table_data if row['Type'] == 'Server') + # Summary table data summary_data = [ local_requests, external_requests, total_requests, total_responses ] - - html_content = '

NTP Module

' # Initialize a dictionary to store timestamps for each unique combination timestamps = defaultdict(list) @@ -114,42 +127,9 @@ def generate_module_report(self): average_time_between_requests[key] = avg_diff - # Add summary table - html_content += (f''' - - - - - - - - - - - - - - - - - -
Requests to local NTP serverRequests to external NTP serversTotal NTP requestsTotal NTP responses
{local_requests}{external_requests}{total_requests}{total_responses}
- ''') - + # Module table data + module_table_data = [] if total_requests + total_responses > 0: - table_content = ''' - - - - - - - - - - - - ''' # Generate the HTML table with the count column for (src, dst, typ, @@ -164,37 +144,44 @@ def generate_module_report(self): else: avg_formatted_time = 'N/A' - table_content += f''' - - - - - - - - ''' - - table_content += ''' - -
SourceDestinationTypeVersionCountSync Request Average
{src}{dst}{typ}{version}{cnt}{avg_formatted_time}
- ''' - html_content += table_content - - else: - html_content += (''' -
-
- No NTP traffic detected from the device -
''') - - LOGGER.debug('Module report:\n' + html_content) + module_table_data.append({ + 'src': src, + 'dst': dst, + 'typ': typ, + 'version': version, + 'cnt': cnt, + 'avg_fmt': avg_formatted_time + }) + + # Handling the possible table split + table_height = (len(module_table_data) + 1) * row_height + page_useful_space = page_max_height - header_height - summary_height + pages = table_height // (page_useful_space) + rows_on_page = ((page_useful_space) // row_height) - 1 + start = 0 + report_html = '' + for page in range(pages+1): + end = start + min(len(module_table_data), rows_on_page) + module_header_repr = module_header if page == 0 else None + page_html = template.render( + base_template=self._base_template_file, + module_header=module_header_repr, + summary_headers=summary_headers, + summary_data=summary_data, + module_data_headers=module_data_headers, + module_data=module_table_data[start:end] + ) + report_html += page_html + start = end + + LOGGER.debug('Module report:\n' + report_html) # Use os.path.join to create the complete file path report_path = os.path.join(self._results_dir, MODULE_REPORT_FILE_NAME) # Write the content to a file with open(report_path, 'w', encoding='utf-8') as file: - file.write(html_content) + file.write(report_html) LOGGER.info('Module report generated at: ' + str(report_path)) diff --git a/modules/test/ntp/resources/report_template.jinja2 b/modules/test/ntp/resources/report_template.jinja2 index 793b65df2..c3601b67b 100644 --- a/modules/test/ntp/resources/report_template.jinja2 +++ b/modules/test/ntp/resources/report_template.jinja2 @@ -1,2 +1,31 @@ {% extends base_template %} -{% block content %}{% endblock %} \ No newline at end of file +{% block content %} +{% if module_data %} + + + + {% for header in module_data_headers %} + + {% endfor %} + + + + {% for row in module_data %} + + + + + + + + + {% endfor %} + +
{{ header }}
{{ row['src'] }}{{ row['dst'] }}{{ row['typ'] }}{{ row['version'] }}{{ row['cnt'] }}{{ row['avg_fmt'] }}
+{% else %} +
+
+ No NTP traffic detected from the device +
+{% endif %} +{% endblock %} \ No newline at end of file From 6756d23309f6baa5d827496e9344461738009161 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Fri, 13 Dec 2024 19:03:05 +0100 Subject: [PATCH 06/17] refactor adding modules reports to the main report --- framework/python/src/common/testreport.py | 47 +++++++++++++------ framework/python/src/core/session.py | 10 ++++ .../python/src/test_orc/test_orchestrator.py | 14 +++++- modules/test/base/python/src/test_module.py | 1 + resources/report/test_report_template.html | 20 ++++---- 5 files changed, 66 insertions(+), 26 deletions(-) diff --git a/framework/python/src/common/testreport.py b/framework/python/src/common/testreport.py index 6acc6eac0..4507096a9 100644 --- a/framework/python/src/common/testreport.py +++ b/framework/python/src/common/testreport.py @@ -16,12 +16,12 @@ from datetime import datetime from weasyprint import HTML from io import BytesIO -from common import util +from common import util, logger from common.statuses import TestrunStatus import base64 import os from test_orc.test_case import TestCase -from jinja2 import Environment, FileSystemLoader +from jinja2 import Environment, FileSystemLoader, BaseLoader from collections import OrderedDict import re from bs4 import BeautifulSoup @@ -34,6 +34,8 @@ TEST_REPORT_STYLES = 'test_report_styles.css' TEST_REPORT_TEMPLATE = 'test_report_template.html' +LOGGER = logger.get_logger('REPORT') + # Locate parent directory current_dir = os.path.dirname(os.path.realpath(__file__)) @@ -65,12 +67,16 @@ def __init__(self, self._total_tests = total_tests self._results = [] self._module_reports = [] + self._module_templates = [] self._report_url = '' self._cur_page = 0 def add_module_reports(self, module_reports): self._module_reports = module_reports + def add_module_templates(self, module_templates): + self._module_templates = module_templates + def get_status(self): return self._status @@ -243,16 +249,20 @@ def to_html(self): optional_steps_to_resolve = self._get_optional_steps_to_resolve(json_data) module_reports = self._get_module_pages() + env_module = Environment(loader=BaseLoader()) pages_num = self._pages_num(json_data) - total_pages = pages_num + len(module_reports) + 1 - if len(steps_to_resolve) > 0: - total_pages += 1 - if (len(optional_steps_to_resolve) > 0 - and json_data['device']['test_pack'] == 'Pilot Assessment' - ): - total_pages += 1 - - return template.render(styles=styles, + module_templates = [ + env_module.from_string(s).render( + json_data=json_data, + device=json_data['device'], + logo=logo, + icon_qualification=icon_qualification, + icon_pilot=icon_pilot, + version=self._version, + ) for s in self._module_templates + ] + + return self._add_page_counter(template.render(styles=styles, logo=logo, icon_qualification=icon_qualification, icon_pilot=icon_pilot, @@ -269,10 +279,19 @@ def to_html(self): optional_steps_to_resolve=optional_steps_to_resolve, module_reports=module_reports, pages_num=pages_num, - total_pages=total_pages, tests_first_page=TESTS_FIRST_PAGE, tests_per_page=TESTS_PER_PAGE, - ) + module_templates=module_templates + )) + + def _add_page_counter(self, html): + # Add page nums and total page + soup = BeautifulSoup(html, features='html5lib') + page_index_divs = soup.find_all('div', class_='page-index') + total_pages = len(page_index_divs) + for index, div in enumerate(page_index_divs): + div.string = f'Page {index+1}/{total_pages}' + return soup.prettify() def _pages_num(self, json_data): @@ -391,7 +410,7 @@ def _get_module_pages(self): if el.name == 'h1': current_size += 40 + h1_padding # Calculating the height of paired tables - elif (el.name == 'div' + elif (el.name == 'div' and el.has_attr('style') and el['style'] == 'display:flex;justify-content:space-between;'): tables = el.findChildren('table', recursive=True) current_size = max( diff --git a/framework/python/src/core/session.py b/framework/python/src/core/session.py index f2e5466d3..29a841c55 100644 --- a/framework/python/src/core/session.py +++ b/framework/python/src/core/session.py @@ -100,6 +100,9 @@ def __init__(self, root_dir): # All historical reports self._module_reports = [] + # Module report templates + self._module_templates = [] + # Parameters specified when starting Testrun self._runtime_params = [] @@ -398,6 +401,9 @@ def get_test_results(self): def get_module_reports(self): return self._module_reports + def get_module_templates(self): + return self._module_templates + def get_report_tests(self): """Returns the current test results in JSON-friendly format (in Python dictionary)""" @@ -465,6 +471,9 @@ def set_test_result_error(self, result): def add_module_report(self, module_report): self._module_reports.append(module_report) + def add_module_template(self, module_template): + self._module_templates.append(module_template) + def get_all_reports(self): reports = [] @@ -789,6 +798,7 @@ def reset(self): self._report_url = None self._total_tests = 0 self._module_reports = [] + self._module_templates = [] self._results = [] self._started = None self._finished = None diff --git a/framework/python/src/test_orc/test_orchestrator.py b/framework/python/src/test_orc/test_orchestrator.py index d133fefd9..13338f24f 100644 --- a/framework/python/src/test_orc/test_orchestrator.py +++ b/framework/python/src/test_orc/test_orchestrator.py @@ -177,6 +177,7 @@ def run_test_modules(self): generated_report_json = self._generate_report() report.from_json(generated_report_json) report.add_module_reports(self.get_session().get_module_reports()) + report.add_module_templates(self.get_session().get_module_templates()) device.add_report(report) self._write_reports(report) @@ -549,8 +550,19 @@ def _run_test_module(self, module): self.get_session().add_module_report(module_report) except (FileNotFoundError, PermissionError): LOGGER.debug("Test module did not produce a html module report") + # Get the Jinja report + jinja_file = f"{module.container_runtime_dir}/{module.name}_report.jinja2" + try: + import shutil + shutil.copy2(jinja_file, '/home/user/projects/testrun/runtime/example.jinja2') + with open(jinja_file, "r", encoding="utf-8") as f: + module_template = f.read() + LOGGER.debug(f"Adding module template for module {module.name}") + self.get_session().add_module_template(module_template) + except (FileNotFoundError, PermissionError): + LOGGER.debug("Test module did not produce a module template") - LOGGER.info(f"Test module {module.name} has finished") + # LOGGER.info(f"Test module {module.name} has finished") def _get_container_logs(self, log_stream): """Resolve all current log data in the containers log_stream diff --git a/modules/test/base/python/src/test_module.py b/modules/test/base/python/src/test_module.py index 73187d789..8d59f975e 100644 --- a/modules/test/base/python/src/test_module.py +++ b/modules/test/base/python/src/test_module.py @@ -18,6 +18,7 @@ import util from datetime import datetime import traceback +import re from common.statuses import TestResult diff --git a/resources/report/test_report_template.html b/resources/report/test_report_template.html index fbd8d1c68..0d08f65ea 100644 --- a/resources/report/test_report_template.html +++ b/resources/report/test_report_template.html @@ -10,10 +10,8 @@ - {% set page_index = namespace(value=0) %} {# Test Results #} {% for page in range(pages_num) %} - {% set page_index.value = page_index.value+1 %}
{{ header_macros.header(loop.first, "Testrun report", json_data, device, logo, icon_qualification, icon_pilot)}} {% if loop.first %} @@ -105,14 +103,13 @@

Results List ({{ successful_tests }}/{{ tot

{% endfor %} {# Steps to resolve Device qualification #} {% if steps_to_resolve|length > 0 and json_data['device']['test_pack'] == 'Device Qualification' %} - {% set page_index.value = page_index.value+1 %}
{{ header_macros.header(False, "Testrun report", json_data, device, logo, icon_qualification, icon_pilot)}}

Non-compliant tests and suggested steps to resolve

@@ -137,13 +134,16 @@

Non-compliant tests and suggested steps to resolve

{% endfor %}
{% endif %} + {# Modules reports Jinja #} + {% for template in module_templates %} + {{ template }} + {% endfor %} {# Modules reports #} {% for module in module_reports %} - {% set page_index.value = page_index.value+1 %}
{{ header_macros.header(False, "Testrun report", json_data, device, logo, icon_qualification, icon_pilot)}}
@@ -151,13 +151,12 @@

Non-compliant tests and suggested steps to resolve

{% endfor %} {# Device profile #} - {% set page_index.value = page_index.value+1 %}
{{ header_macros.header(False, "Testrun report", json_data, device, logo, icon_qualification, icon_pilot)}}

Device profile

@@ -186,13 +185,12 @@

Device profile

{# Pilot steps to resolve#} {% if json_data['device']['test_pack'] == 'Pilot Assessment' and optional_steps_to_resolve|length > 0 %} - {% set page_index.value = page_index.value + 1 %}
{{ header_macros.header(False, "Testrun report", json_data, device, logo, icon_qualification, icon_pilot)}}

Recommendations for Device Qualification

@@ -233,7 +231,7 @@

Recommendations for Device Qualification

{% endfor %}
{% endif %} From fb30203f497289b606ff3a394796386abd89e80b Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Fri, 13 Dec 2024 19:18:59 +0100 Subject: [PATCH 07/17] pylint --- framework/python/src/core/session.py | 4 ++-- framework/python/src/test_orc/test_orchestrator.py | 2 -- modules/test/base/python/src/test_module.py | 7 +++---- modules/test/ntp/python/src/ntp_module.py | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/framework/python/src/core/session.py b/framework/python/src/core/session.py index 29a841c55..ffbb9d26f 100644 --- a/framework/python/src/core/session.py +++ b/framework/python/src/core/session.py @@ -667,7 +667,7 @@ def _remove_invalid_questions(self, questions): valid_questions.append(question) else: - LOGGER.debug(f'Removed unrecognised question: {question["question"]}') + LOGGER.debug(f'Removed unrecognised question: {question["question"]}') # pylint: disable=W1405 # Return the list of valid questions return valid_questions @@ -713,7 +713,7 @@ def validate_profile_json(self, profile_json): question.get('question')) if format_q is None: - LOGGER.error(f'Unrecognised question: {question.get("question")}') + LOGGER.error(f'Unrecognised question: {question.get("question")}') # pylint: disable=W1405 # Just ignore additional questions continue diff --git a/framework/python/src/test_orc/test_orchestrator.py b/framework/python/src/test_orc/test_orchestrator.py index 13338f24f..8309a48d1 100644 --- a/framework/python/src/test_orc/test_orchestrator.py +++ b/framework/python/src/test_orc/test_orchestrator.py @@ -553,8 +553,6 @@ def _run_test_module(self, module): # Get the Jinja report jinja_file = f"{module.container_runtime_dir}/{module.name}_report.jinja2" try: - import shutil - shutil.copy2(jinja_file, '/home/user/projects/testrun/runtime/example.jinja2') with open(jinja_file, "r", encoding="utf-8") as f: module_template = f.read() LOGGER.debug(f"Adding module template for module {module.name}") diff --git a/modules/test/base/python/src/test_module.py b/modules/test/base/python/src/test_module.py index 8d59f975e..42ee3ff85 100644 --- a/modules/test/base/python/src/test_module.py +++ b/modules/test/base/python/src/test_module.py @@ -18,7 +18,6 @@ import util from datetime import datetime import traceback -import re from common.statuses import TestResult @@ -140,14 +139,14 @@ def run_tests(self): else: result = getattr(self, test_method_name)() except Exception as e: # pylint: disable=W0718 - LOGGER.error(f'An error occurred whilst running {test["name"]}') + LOGGER.error(f'An error occurred whilst running {test["name"]}') # pylint: disable=W1405 LOGGER.error(e) traceback.print_exc() else: - LOGGER.error(f'Test {test["name"]} has not been implemented') + LOGGER.error(f'Test {test["name"]} has not been implemented') # pylint: disable=W1405 result = TestResult.ERROR, 'This test could not be found' else: - LOGGER.debug(f'Test {test["name"]} is disabled') + LOGGER.debug(f'Test {test["name"]} is disabled') # pylint: disable=W1405 result = (TestResult.DISABLED, 'This test did not run because it is disabled') diff --git a/modules/test/ntp/python/src/ntp_module.py b/modules/test/ntp/python/src/ntp_module.py index 411776899..17f63960a 100644 --- a/modules/test/ntp/python/src/ntp_module.py +++ b/modules/test/ntp/python/src/ntp_module.py @@ -30,7 +30,7 @@ class NTPModule(TestModule): """NTP Test module""" - def __init__(self, + def __init__(self, # pylint: disable=R0917 module, conf_file=None, results_dir=None, From d87f567fcf59d630a9cd35cb45751a0939d0e1d7 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Sat, 14 Dec 2024 18:03:18 +0100 Subject: [PATCH 08/17] generating module report using jinja --- .../services/python/src/services_module.py | 101 ++++++++---------- .../services/resources/report_template.jinja2 | 29 +++++ modules/test/services/services.Dockerfile | 5 +- 3 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 modules/test/services/resources/report_template.jinja2 diff --git a/modules/test/services/python/src/services_module.py b/modules/test/services/python/src/services_module.py index 1a783e7dc..b059d02b0 100644 --- a/modules/test/services/python/src/services_module.py +++ b/modules/test/services/python/src/services_module.py @@ -19,17 +19,19 @@ import xmltodict from test_module import TestModule import os +from jinja2 import Environment, FileSystemLoader LOG_NAME = 'test_services' -MODULE_REPORT_FILE_NAME = 'services_report.html' +MODULE_REPORT_FILE_NAME = 'services_report.jinja2' NMAP_SCAN_RESULTS_SCAN_FILE = 'services_scan_results.json' LOGGER = None +REPORT_TEMPLATE_FILE = 'report_template.jinja2' class ServicesModule(TestModule): """Services Test module""" - def __init__(self, + def __init__(self, # pylint: disable=R0917 module, conf_file=None, results_dir=None, @@ -52,6 +54,22 @@ def __init__(self, self._run_nmap() def generate_module_report(self): + # Load Jinja2 template + loader=FileSystemLoader(self._report_template_folder) + template = Environment(loader=loader).get_template(REPORT_TEMPLATE_FILE) + module_header = 'Services Module' + summary_headers = [ + 'TCP ports open', + 'UDP ports open', + 'Total ports open', + ] + module_data_headers = [ + 'Port', + 'State', + 'Service', + 'Version', + ] + # Use os.path.join to create the complete file path nmap_scan_results_file = os.path.join(self._nmap_scan_results_path, NMAP_SCAN_RESULTS_SCAN_FILE) @@ -81,65 +99,32 @@ def generate_module_report(self): else: udp_open += 1 - html_content = '

Services Module

' - - # Add summary table - html_content += (f''' - - - - - - - - - - - - - - -
TCP ports openUDP ports openTotal ports open
{tcp_open}{udp_open}{tcp_open + udp_open}
- ''') + summary_data = [ + tcp_open, + udp_open, + tcp_open + udp_open, + ] + module_data = [] if (tcp_open + udp_open) > 0: - - table_content = ''' - - - - - - - - - - ''' - for row in nmap_table_data: - - table_content += (f''' - - - - - - ''') - - table_content += ''' - -
PortStateServiceVersion
{row['Port']}/{row['Type']}{row['State']}{row['Service']}{row['Version']}
- ''' - - html_content += table_content - - else: - - html_content += (''' -
-
- No open ports detected -
''') + port = row['Port'] + type_ = row['Type'] + module_data.append({ + 'Port': f'{port}/{type_}', + 'State': row['State'], + 'Service': row['Service'], + 'Version': row['Version'], + }) + + html_content = template.render( + base_template=self._base_template_file, + module_header=module_header, + summary_headers=summary_headers, + summary_data=summary_data, + module_data_headers=module_data_headers, + module_data=module_data, + ) LOGGER.debug('Module report:\n' + html_content) diff --git a/modules/test/services/resources/report_template.jinja2 b/modules/test/services/resources/report_template.jinja2 new file mode 100644 index 000000000..cb42385fc --- /dev/null +++ b/modules/test/services/resources/report_template.jinja2 @@ -0,0 +1,29 @@ +{% extends base_template %} +{% block content %} +{% if module_data %} + + + + {% for header in module_data_headers %} + + {% endfor %} + + + + {% for row in module_data %} + + + + + + + {% endfor %} + +
{{ header }}
{{ row['Port'] }}{{ row['State'] }}{{ row['Service'] }}{{ row['Version'] }}
+{% else %} +
+
+ No open ports detected +
+{% endif %} +{% endblock %} \ No newline at end of file diff --git a/modules/test/services/services.Dockerfile b/modules/test/services/services.Dockerfile index 8dcaafcc1..1277c2f8d 100644 --- a/modules/test/services/services.Dockerfile +++ b/modules/test/services/services.Dockerfile @@ -31,4 +31,7 @@ COPY $MODULE_DIR/conf /testrun/conf COPY $MODULE_DIR/bin /testrun/bin # Copy over all python files -COPY $MODULE_DIR/python /testrun/python \ No newline at end of file +COPY $MODULE_DIR/python /testrun/python + +# Copy Jinja template +COPY $MODULE_DIR/resources/report_template.jinja2 $REPORT_TEMPLATE_PATH/ \ No newline at end of file From 098538123db6899b530aa5f342939aacd7beca8f Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Tue, 17 Dec 2024 21:49:59 +0100 Subject: [PATCH 09/17] rename jinja report --- framework/python/src/test_orc/test_orchestrator.py | 2 +- modules/test/ntp/python/src/ntp_module.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/python/src/test_orc/test_orchestrator.py b/framework/python/src/test_orc/test_orchestrator.py index 8309a48d1..787de08e6 100644 --- a/framework/python/src/test_orc/test_orchestrator.py +++ b/framework/python/src/test_orc/test_orchestrator.py @@ -551,7 +551,7 @@ def _run_test_module(self, module): except (FileNotFoundError, PermissionError): LOGGER.debug("Test module did not produce a html module report") # Get the Jinja report - jinja_file = f"{module.container_runtime_dir}/{module.name}_report.jinja2" + jinja_file = f"{module.container_runtime_dir}/{module.name}_report.j2.html" try: with open(jinja_file, "r", encoding="utf-8") as f: module_template = f.read() diff --git a/modules/test/ntp/python/src/ntp_module.py b/modules/test/ntp/python/src/ntp_module.py index 17f63960a..6a64b101c 100644 --- a/modules/test/ntp/python/src/ntp_module.py +++ b/modules/test/ntp/python/src/ntp_module.py @@ -19,7 +19,7 @@ from jinja2 import Environment, FileSystemLoader LOG_NAME = 'test_ntp' -MODULE_REPORT_FILE_NAME = 'ntp_report.jinja2' +MODULE_REPORT_FILE_NAME = 'ntp_report.j2.html' NTP_SERVER_CAPTURE_FILE = '/runtime/network/ntp.pcap' STARTUP_CAPTURE_FILE = '/runtime/device/startup.pcap' MONITOR_CAPTURE_FILE = '/runtime/device/monitor.pcap' From 6c666e4c81a80f50e44c5bbdec18f41c142867b7 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 18 Dec 2024 01:14:46 +0100 Subject: [PATCH 10/17] unit tests --- testing/unit/ntp/ntp_module_test.py | 13 +- .../unit/ntp/reports/ntp_report_local.html | 294 +++++++++++------- .../ntp/reports/ntp_report_local_no_ntp.html | 95 ++++-- .../ntp/templates/module_report_base.jinja2 | 55 ++++ .../unit/ntp/templates/report_template.jinja2 | 31 ++ 5 files changed, 346 insertions(+), 142 deletions(-) create mode 100644 testing/unit/ntp/templates/module_report_base.jinja2 create mode 100644 testing/unit/ntp/templates/report_template.jinja2 diff --git a/testing/unit/ntp/ntp_module_test.py b/testing/unit/ntp/ntp_module_test.py index 52bd32aa9..1dda0340e 100644 --- a/testing/unit/ntp/ntp_module_test.py +++ b/testing/unit/ntp/ntp_module_test.py @@ -26,6 +26,10 @@ OUTPUT_DIR = os.path.join(TEST_FILES_DIR,'output/') REPORTS_DIR = os.path.join(TEST_FILES_DIR,'reports/') CAPTURES_DIR = os.path.join(TEST_FILES_DIR,'captures/') +MODULE_FILES_DIR = 'modules/test/' + MODULE +TEMPLATE_DIR = os.path.join(TEST_FILES_DIR, 'templates') +TEMPLATE_FILE = 'report_template.jinja2' +BASE_TEMPLATE_FILE = 'module_report_base.jinja2' LOCAL_REPORT = os.path.join(REPORTS_DIR,'ntp_report_local.html') LOCAL_REPORT_NO_NTP = os.path.join(REPORTS_DIR,'ntp_report_local_no_ntp.html') @@ -52,6 +56,8 @@ def ntp_module_report_test(self): ntp_server_capture_file=NTP_SERVER_CAPTURE_FILE, startup_capture_file=STARTUP_CAPTURE_FILE, monitor_capture_file=MONITOR_CAPTURE_FILE) + setattr(ntp_module, '_report_template_folder', TEMPLATE_DIR) + setattr(ntp_module, '_base_template_file', BASE_TEMPLATE_FILE) report_out_path = ntp_module.generate_module_report() @@ -67,7 +73,6 @@ def ntp_module_report_test(self): new_report_name = 'ntp_local.html' new_report_path = os.path.join(OUTPUT_DIR, new_report_name) shutil.copy(report_out_path, new_report_path) - self.assertEqual(report_out, report_local) # Test the module report generation if no DNS traffic @@ -100,12 +105,15 @@ def ntp_module_report_no_ntp_test(self): wrpcap(startup_cap_file, packets_startup) wrpcap(monitor_cap_file, packets_monitor) - ntp_module = NTPModule(module='dns', + ntp_module = NTPModule(module=MODULE, results_dir=OUTPUT_DIR, ntp_server_capture_file=ntp_server_cap_file, startup_capture_file=startup_cap_file, monitor_capture_file=monitor_cap_file) + setattr(ntp_module, '_report_template_folder', TEMPLATE_DIR) + setattr(ntp_module, '_base_template_file', BASE_TEMPLATE_FILE) + report_out_path = ntp_module.generate_module_report() # Read the generated report @@ -136,4 +144,3 @@ def ntp_module_report_no_ntp_test(self): if not test_result.wasSuccessful(): sys.exit(1) # Return a non-zero exit code for failures sys.exit(0) # Return zero for success - \ No newline at end of file diff --git a/testing/unit/ntp/reports/ntp_report_local.html b/testing/unit/ntp/reports/ntp_report_local.html index 1fe5e3f3a..89e736e17 100644 --- a/testing/unit/ntp/reports/ntp_report_local.html +++ b/testing/unit/ntp/reports/ntp_report_local.html @@ -1,115 +1,179 @@ -

NTP Module

- - - - - - - - - - - - - - - - - -
Requests to local NTP serverRequests to external NTP serversTotal NTP requestsTotal NTP responses
6338101104
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SourceDestinationTypeVersionCountSync Request Average
10.10.10.15216.239.35.12Client4837.942 seconds
216.239.35.1210.10.10.15Server48N/A
10.10.10.15216.239.35.4Client4837.834 seconds
216.239.35.410.10.10.15Server48N/A
10.10.10.15216.239.35.8Client4838.056 seconds
216.239.35.810.10.10.15Server48N/A
10.10.10.15216.239.35.0Client41420.601 seconds
216.239.35.010.10.10.15Server417N/A
10.10.10.1510.10.10.5Client46313.057 seconds
10.10.10.510.10.10.15Server463N/A
- \ No newline at end of file + +
+
+
+ {# Badge #} +

+ {% if json_data['device']['test_pack'] == 'Device Qualification' %} + + Device Qualification + {% else %} + + Pilot Assessment + {% endif %} +

+ {{ title }} +
+ + {{ device['manufacturer'] }} + {{ device['model']}} + + Testrun +
+ +
+ +

NTP Module

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Requests to local NTP serverRequests to external NTP serversTotal NTP requestsTotal NTP responses
6338101104
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SourceDestinationTypeVersionCountSync Request Average
10.10.10.15216.239.35.12Client4837.942 seconds
216.239.35.1210.10.10.15Server48N/A
10.10.10.15216.239.35.4Client4837.834 seconds
216.239.35.410.10.10.15Server48N/A
10.10.10.15216.239.35.8Client4838.056 seconds
216.239.35.810.10.10.15Server48N/A
10.10.10.15216.239.35.0Client41420.601 seconds
216.239.35.010.10.10.15Server417N/A
10.10.10.1510.10.10.5Client46313.057 seconds
10.10.10.510.10.10.15Server463N/A
+ + +
+ + +
+
diff --git a/testing/unit/ntp/reports/ntp_report_local_no_ntp.html b/testing/unit/ntp/reports/ntp_report_local_no_ntp.html index c93ab885f..abe616a38 100644 --- a/testing/unit/ntp/reports/ntp_report_local_no_ntp.html +++ b/testing/unit/ntp/reports/ntp_report_local_no_ntp.html @@ -1,24 +1,71 @@ -

NTP Module

- - - - - - - - - - - - - - - - - -
Requests to local NTP serverRequests to external NTP serversTotal NTP requestsTotal NTP responses
0000
- -
-
- No NTP traffic detected from the device -
\ No newline at end of file + +
+
+
+ {# Badge #} +

+ {% if json_data['device']['test_pack'] == 'Device Qualification' %} + + Device Qualification + {% else %} + + Pilot Assessment + {% endif %} +

+ {{ title }} +
+ + {{ device['manufacturer'] }} + {{ device['model']}} + + Testrun +
+ +
+ +

NTP Module

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Requests to local NTP serverRequests to external NTP serversTotal NTP requestsTotal NTP responses
0000
+ + +
+
+ No NTP traffic detected from the device +
+ + +
+ + +
+
diff --git a/testing/unit/ntp/templates/module_report_base.jinja2 b/testing/unit/ntp/templates/module_report_base.jinja2 new file mode 100644 index 000000000..009b7646d --- /dev/null +++ b/testing/unit/ntp/templates/module_report_base.jinja2 @@ -0,0 +1,55 @@ +{% raw %} +
+
+
+ {# Badge #} +

+ {% if json_data['device']['test_pack'] == 'Device Qualification' %} + + Device Qualification + {% else %} + + Pilot Assessment + {% endif %} +

+ {{ title }} +
+ + {{ device['manufacturer'] }} + {{ device['model']}} + + Testrun +
+{% endraw %} +
+ {% if module_header %} +

{{ module_header }}

+ + {% else %} +
+ {% endif %} + + + {% for header in summary_headers %} + + {% endfor %} + + + + + {% for cell in summary_data %} + + {% endfor %} + + +
{{ header }}
{{ cell }}
+ {% block content %}{% endblock content %} +
+{% raw %} + +
+
+{% endraw %} \ No newline at end of file diff --git a/testing/unit/ntp/templates/report_template.jinja2 b/testing/unit/ntp/templates/report_template.jinja2 new file mode 100644 index 000000000..c3601b67b --- /dev/null +++ b/testing/unit/ntp/templates/report_template.jinja2 @@ -0,0 +1,31 @@ +{% extends base_template %} +{% block content %} +{% if module_data %} + + + + {% for header in module_data_headers %} + + {% endfor %} + + + + {% for row in module_data %} + + + + + + + + + {% endfor %} + +
{{ header }}
{{ row['src'] }}{{ row['dst'] }}{{ row['typ'] }}{{ row['version'] }}{{ row['cnt'] }}{{ row['avg_fmt'] }}
+{% else %} +
+
+ No NTP traffic detected from the device +
+{% endif %} +{% endblock %} \ No newline at end of file From 83d1c92ea2ecea3b11598e3b00dc646e641eb8bd Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 18 Dec 2024 01:50:29 +0100 Subject: [PATCH 11/17] remove unused mocks --- testing/unit/ntp/ntp_module_test.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/testing/unit/ntp/ntp_module_test.py b/testing/unit/ntp/ntp_module_test.py index 1dda0340e..3b865d531 100644 --- a/testing/unit/ntp/ntp_module_test.py +++ b/testing/unit/ntp/ntp_module_test.py @@ -27,9 +27,6 @@ REPORTS_DIR = os.path.join(TEST_FILES_DIR,'reports/') CAPTURES_DIR = os.path.join(TEST_FILES_DIR,'captures/') MODULE_FILES_DIR = 'modules/test/' + MODULE -TEMPLATE_DIR = os.path.join(TEST_FILES_DIR, 'templates') -TEMPLATE_FILE = 'report_template.jinja2' -BASE_TEMPLATE_FILE = 'module_report_base.jinja2' LOCAL_REPORT = os.path.join(REPORTS_DIR,'ntp_report_local.html') LOCAL_REPORT_NO_NTP = os.path.join(REPORTS_DIR,'ntp_report_local_no_ntp.html') @@ -56,8 +53,6 @@ def ntp_module_report_test(self): ntp_server_capture_file=NTP_SERVER_CAPTURE_FILE, startup_capture_file=STARTUP_CAPTURE_FILE, monitor_capture_file=MONITOR_CAPTURE_FILE) - setattr(ntp_module, '_report_template_folder', TEMPLATE_DIR) - setattr(ntp_module, '_base_template_file', BASE_TEMPLATE_FILE) report_out_path = ntp_module.generate_module_report() @@ -111,9 +106,6 @@ def ntp_module_report_no_ntp_test(self): startup_capture_file=startup_cap_file, monitor_capture_file=monitor_cap_file) - setattr(ntp_module, '_report_template_folder', TEMPLATE_DIR) - setattr(ntp_module, '_base_template_file', BASE_TEMPLATE_FILE) - report_out_path = ntp_module.generate_module_report() # Read the generated report From 831e5c055464c5d21361657dde44360bd169c543 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 18 Dec 2024 01:57:41 +0100 Subject: [PATCH 12/17] delete unused templates --- .../ntp/templates/module_report_base.jinja2 | 55 ------------------- .../unit/ntp/templates/report_template.jinja2 | 31 ----------- 2 files changed, 86 deletions(-) delete mode 100644 testing/unit/ntp/templates/module_report_base.jinja2 delete mode 100644 testing/unit/ntp/templates/report_template.jinja2 diff --git a/testing/unit/ntp/templates/module_report_base.jinja2 b/testing/unit/ntp/templates/module_report_base.jinja2 deleted file mode 100644 index 009b7646d..000000000 --- a/testing/unit/ntp/templates/module_report_base.jinja2 +++ /dev/null @@ -1,55 +0,0 @@ -{% raw %} -
-
-
- {# Badge #} -

- {% if json_data['device']['test_pack'] == 'Device Qualification' %} - - Device Qualification - {% else %} - - Pilot Assessment - {% endif %} -

- {{ title }} -
- - {{ device['manufacturer'] }} - {{ device['model']}} - - Testrun -
-{% endraw %} -
- {% if module_header %} -

{{ module_header }}

- - {% else %} -
- {% endif %} - - - {% for header in summary_headers %} - - {% endfor %} - - - - - {% for cell in summary_data %} - - {% endfor %} - - -
{{ header }}
{{ cell }}
- {% block content %}{% endblock content %} -
-{% raw %} - -
-
-{% endraw %} \ No newline at end of file diff --git a/testing/unit/ntp/templates/report_template.jinja2 b/testing/unit/ntp/templates/report_template.jinja2 deleted file mode 100644 index c3601b67b..000000000 --- a/testing/unit/ntp/templates/report_template.jinja2 +++ /dev/null @@ -1,31 +0,0 @@ -{% extends base_template %} -{% block content %} -{% if module_data %} - - - - {% for header in module_data_headers %} - - {% endfor %} - - - - {% for row in module_data %} - - - - - - - - - {% endfor %} - -
{{ header }}
{{ row['src'] }}{{ row['dst'] }}{{ row['typ'] }}{{ row['version'] }}{{ row['cnt'] }}{{ row['avg_fmt'] }}
-{% else %} -
-
- No NTP traffic detected from the device -
-{% endif %} -{% endblock %} \ No newline at end of file From 524aedb97b97a931b549e43373b6c5f01b8986fe Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 18 Dec 2024 02:04:34 +0100 Subject: [PATCH 13/17] change style to id for paired tables --- framework/python/src/common/testreport.py | 4 ++-- modules/test/tls/python/src/tls_module.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/python/src/common/testreport.py b/framework/python/src/common/testreport.py index 4507096a9..df31a5441 100644 --- a/framework/python/src/common/testreport.py +++ b/framework/python/src/common/testreport.py @@ -410,8 +410,8 @@ def _get_module_pages(self): if el.name == 'h1': current_size += 40 + h1_padding # Calculating the height of paired tables - elif (el.name == 'div' and el.has_attr('style') - and el['style'] == 'display:flex;justify-content:space-between;'): + elif (el.name == 'div' and el.has_attr('id') + and el['id'] == 'paired'): tables = el.findChildren('table', recursive=True) current_size = max( map(lambda t: len( diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index 1405ad31c..ca7bed260 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -229,7 +229,7 @@ def generate_module_report(self): summary_table = f'\n{summary_table}' summary_table += f''' -
+
Certificate Information
{cert_table} From daa69ad6768dc2d623d7c985d2ee0c3635eb39f5 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 18 Dec 2024 02:32:35 +0100 Subject: [PATCH 14/17] fix tls unit tests --- testing/unit/tls/reports/tls_report_ext_local.html | 4 ++-- testing/unit/tls/reports/tls_report_local.html | 8 ++++---- testing/unit/tls/reports/tls_report_single.html | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/testing/unit/tls/reports/tls_report_ext_local.html b/testing/unit/tls/reports/tls_report_ext_local.html index 7e691f66a..bde424a0e 100644 --- a/testing/unit/tls/reports/tls_report_ext_local.html +++ b/testing/unit/tls/reports/tls_report_ext_local.html @@ -22,7 +22,7 @@

TLS Module

-
+
Certificate Information
@@ -121,7 +121,7 @@
Certificate Extensions
-
+
Certificate Information
diff --git a/testing/unit/tls/reports/tls_report_local.html b/testing/unit/tls/reports/tls_report_local.html index 72b2e5a1a..4d1af0404 100644 --- a/testing/unit/tls/reports/tls_report_local.html +++ b/testing/unit/tls/reports/tls_report_local.html @@ -22,7 +22,7 @@

TLS Module

-
+
Certificate Information
@@ -151,7 +151,7 @@
Certificate Extensions
-
+
Certificate Information
@@ -281,7 +281,7 @@
Certificate Extensions
-
+
Certificate Information
@@ -411,7 +411,7 @@
Certificate Extensions
-
+
Certificate Information
diff --git a/testing/unit/tls/reports/tls_report_single.html b/testing/unit/tls/reports/tls_report_single.html index 36adffb94..0f6a5a4d6 100644 --- a/testing/unit/tls/reports/tls_report_single.html +++ b/testing/unit/tls/reports/tls_report_single.html @@ -22,7 +22,7 @@

TLS Module

-
+
Certificate Information
@@ -125,7 +125,7 @@
Subject Information
-
+
Certificate Information
From af2d320f660992f5ecb5bee7f473c4ad019d6cd2 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 18 Dec 2024 11:52:55 +0100 Subject: [PATCH 15/17] table width --- modules/test/services/resources/report_template.jinja2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/test/services/resources/report_template.jinja2 b/modules/test/services/resources/report_template.jinja2 index cb42385fc..c9b1438ae 100644 --- a/modules/test/services/resources/report_template.jinja2 +++ b/modules/test/services/resources/report_template.jinja2 @@ -1,7 +1,7 @@ {% extends base_template %} {% block content %} {% if module_data %} - +
{% for header in module_data_headers %} From 0ad5b2ee3afdb268295b43d278c47c76cc6704c8 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 18 Dec 2024 11:53:10 +0100 Subject: [PATCH 16/17] rename report file --- modules/test/services/python/src/services_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/test/services/python/src/services_module.py b/modules/test/services/python/src/services_module.py index b059d02b0..b6787e124 100644 --- a/modules/test/services/python/src/services_module.py +++ b/modules/test/services/python/src/services_module.py @@ -22,7 +22,7 @@ from jinja2 import Environment, FileSystemLoader LOG_NAME = 'test_services' -MODULE_REPORT_FILE_NAME = 'services_report.jinja2' +MODULE_REPORT_FILE_NAME = 'services_report.j2.html' NMAP_SCAN_RESULTS_SCAN_FILE = 'services_scan_results.json' LOGGER = None REPORT_TEMPLATE_FILE = 'report_template.jinja2' From ff35c944f22f9f73d8a2ab58612f946972bfa618 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 18 Dec 2024 12:33:50 +0100 Subject: [PATCH 17/17] unit tests --- .../services_report_all_closed_local.html | 88 +++++++--- .../reports/services_report_local.html | 150 ++++++++++++------ 2 files changed, 169 insertions(+), 69 deletions(-) diff --git a/testing/unit/services/reports/services_report_all_closed_local.html b/testing/unit/services/reports/services_report_all_closed_local.html index 356a82d35..01ac50676 100644 --- a/testing/unit/services/reports/services_report_all_closed_local.html +++ b/testing/unit/services/reports/services_report_all_closed_local.html @@ -1,21 +1,67 @@ -

Services Module

-
- - - - - - - - - - - - - -
TCP ports openUDP ports openTotal ports open
000
- -
-
- No open ports detected -
\ No newline at end of file + +
+
+
+ {# Badge #} +

+ {% if json_data['device']['test_pack'] == 'Device Qualification' %} + + Device Qualification + {% else %} + + Pilot Assessment + {% endif %} +

+ {{ title }} +
+ + {{ device['manufacturer'] }} + {{ device['model']}} + + Testrun +
+ +
+ +

Services Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
TCP ports openUDP ports openTotal ports open
000
+ + +
+
+ No open ports detected +
+ + +
+ + +
+
diff --git a/testing/unit/services/reports/services_report_local.html b/testing/unit/services/reports/services_report_local.html index ce601cfc0..71f929aeb 100644 --- a/testing/unit/services/reports/services_report_local.html +++ b/testing/unit/services/reports/services_report_local.html @@ -1,48 +1,102 @@ -

Services Module

- - - - - - - - - - - - - - -
TCP ports openUDP ports openTotal ports open
303
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PortStateServiceVersion
22/tcpopenssh8.8 protocol 2.0
443/tcpopenhttp
502/tcpopenmbap
- \ No newline at end of file + +
+
+
+ {# Badge #} +

+ {% if json_data['device']['test_pack'] == 'Device Qualification' %} + + Device Qualification + {% else %} + + Pilot Assessment + {% endif %} +

+ {{ title }} +
+ + {{ device['manufacturer'] }} + {{ device['model']}} + + Testrun +
+ +
+ +

Services Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
TCP ports openUDP ports openTotal ports open
303
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PortStateServiceVersion
22/tcpopenssh8.8 protocol 2.0
443/tcpopenhttp
502/tcpopenmbap
+ + +
+ + +
+