From 36d750c8cc1ba1db3c5813c504f302bcd239c76e Mon Sep 17 00:00:00 2001 From: jhughesbiot Date: Tue, 8 Oct 2024 13:41:13 -0600 Subject: [PATCH 01/25] Re-add TLS module report and udpate to new format --- modules/test/tls/conf/module_config.json | 2 +- modules/test/tls/python/src/run.py | 2 +- modules/test/tls/python/src/tls_module.py | 358 +++++++++++++--------- testing/unit/tls/tls_module_test.py | 145 +++++---- 4 files changed, 290 insertions(+), 217 deletions(-) diff --git a/modules/test/tls/conf/module_config.json b/modules/test/tls/conf/module_config.json index 933efd3ad..71074f1aa 100644 --- a/modules/test/tls/conf/module_config.json +++ b/modules/test/tls/conf/module_config.json @@ -9,7 +9,7 @@ "docker": { "depends_on": "base", "enable_container": true, - "timeout": 300 + "timeout": 420 }, "tests":[ { diff --git a/modules/test/tls/python/src/run.py b/modules/test/tls/python/src/run.py index 89de9f65e..2b7ea7e0f 100644 --- a/modules/test/tls/python/src/run.py +++ b/modules/test/tls/python/src/run.py @@ -37,7 +37,7 @@ def __init__(self, module): self._test_module = TLSModule(module) self._test_module.run_tests() - #self._test_module.generate_module_report() + self._test_module.generate_module_report() def _handler(self, signum): LOGGER.debug('SigtermEnum: ' + str(signal.SIGTERM)) diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index 186766b17..d28813d4e 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -14,9 +14,12 @@ """TLS test module""" from test_module import TestModule from tls_util import TLSUtil +import os import pyshark from cryptography import x509 from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.asymmetric import rsa, dsa, ec LOG_NAME = 'test_tls' MODULE_REPORT_FILE_NAME = 'tls_report.html' @@ -50,146 +53,221 @@ def __init__(self, LOGGER = self._get_logger() self._tls_util = TLSUtil(LOGGER) - # def generate_module_report(self): - # html_content = '

TLS Module

' - - # # List of capture files to scan - # pcap_files = [ - # self.startup_capture_file, self.monitor_capture_file, - # self.tls_capture_file - # ] - # certificates = self.extract_certificates_from_pcap(pcap_files, - # self._device_mac) - # if len(certificates) > 0: - - # # Add summary table - # summary_table = ''' - # - # - # - # - # - # - # - # - # - # - # - # ''' - - # # table_content = ''' - # #
ExpiryLengthTypePort numberSigned by
- # # - # # - # # - # # - # # - # # - # # - # # - # # - # # ''' - - # cert_tables = [] - # for cert_num, ((ip_address, port), cert) in enumerate( - # certificates.items()): - - # # Extract certificate data - # not_valid_before = cert.not_valid_before - # not_valid_after = cert.not_valid_after - # version_value = f'{cert.version.value + 1} ({hex(cert.version.value)})' - # signature_alg_value = cert.signature_algorithm_oid._name # pylint: disable=W0212 - # not_before = str(not_valid_before) - # not_after = str(not_valid_after) - # public_key = cert.public_key() - # signed_by = 'None' - # if isinstance(public_key, rsa.RSAPublicKey): - # public_key_type = 'RSA' - # elif isinstance(public_key, dsa.DSAPublicKey): - # public_key_type = 'DSA' - # elif isinstance(public_key, ec.EllipticCurvePublicKey): - # public_key_type = 'EC' - # else: - # public_key_type = 'Unknown' - # # Calculate certificate length - # cert_length = len(cert.public_bytes( - # encoding=serialization.Encoding.DER)) - - # # Generate the Certificate table - # # cert_table = (f'| Property | Value |\n' - # # f'|---|---|\n' - # # f"| {'Version':<17} | {version_value:^25} |\n" - # # f"| {'Signature Alg.':<17} | - # {signature_alg_value:^25} |\n" - # # f"| {'Validity from':<17} | {not_before:^25} |\n" - # # f"| {'Valid to':<17} | {not_after:^25} |") - - # # Generate the Subject table - # subj_table = ('| Distinguished Name | Value |\n' - # '|---|---|') - # for val in cert.subject.rdns: - # dn = val.rfc4514_string().split('=') - # subj_table += f'\n| {dn[0]} | {dn[1]}' - - # # Generate the Issuer table - # iss_table = ('| Distinguished Name | Value |\n' - # '|---|---|') - # for val in cert.issuer.rdns: - # dn = val.rfc4514_string().split('=') - # iss_table += f'\n| {dn[0]} | {dn[1]}' - # if 'CN' in dn[0]: - # signed_by = dn[1] - - # ext_table = None - # # if cert.extensions: - # # ext_table = ('| Extension | Value |\n' - # # '|---|---|') - # # for extension in cert.extensions: - # # for extension_value in extension.value: - # # ext_table += f'''\n| {extension.oid._name} | - # # {extension_value.value}''' # pylint: disable=W0212 - # # cert_table = f'### Certificate\n{cert_table}' - # # cert_table += f'\n\n### Subject\n{subj_table}' - # # cert_table += f'\n\n### Issuer\n{iss_table}' - # # if ext_table is not None: - # # cert_table += f'\n\n### Extensions\n{ext_table}' - # # cert_tables.append(cert_table) - - # summary_table += f''' - # - # - # - # - # - # - # - # ''' - - # summary_table += ''' - # - #
ExpiryLengthTypePort numberSigned by
{not_after}{cert_length}{public_key_type}{port}{signed_by}
- # ''' - - # html_content += summary_table - - # else: - # html_content += (''' - #
- #
- # No TLS certificates found on the device - #
''') - - # LOGGER.debug('Module report:\n' + html_content) - - # # 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) - - # LOGGER.info('Module report generated at: ' + str(report_path)) - # return report_path + def generate_module_report(self): + html_content = '

TLS Module

' + + # List of capture files to scan + pcap_files = [ + self.startup_capture_file, self.monitor_capture_file, + self.tls_capture_file + ] + certificates = self.extract_certificates_from_pcap(pcap_files, + self._device_mac) + if len(certificates) > 0: + + # Add summary table + summary_table = ''' + + + + + + + + + + + + ''' + + cert_tables = [] + for cert_num, ((ip_address, port), + cert) in enumerate(certificates.items()): + + # Extract certificate data + not_valid_before = cert.not_valid_before + not_valid_after = cert.not_valid_after + version_value = f'{cert.version.value + 1} ({hex(cert.version.value)})' + signature_alg_value = cert.signature_algorithm_oid._name # pylint: disable=W0212 + not_before = str(not_valid_before) + not_after = str(not_valid_after) + public_key = cert.public_key() + signed_by = 'None' + if isinstance(public_key, rsa.RSAPublicKey): + public_key_type = 'RSA' + elif isinstance(public_key, dsa.DSAPublicKey): + public_key_type = 'DSA' + elif isinstance(public_key, ec.EllipticCurvePublicKey): + public_key_type = 'EC' + else: + public_key_type = 'Unknown' + # Calculate certificate length + cert_length = len( + cert.public_bytes(encoding=serialization.Encoding.DER)) + + # Generate the Certificate table + cert_table = f''' +

Certificate

+
ExpiryLengthTypePort numberSigned by
+ + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version{version_value}
Signature Alg.{signature_alg_value}
Validity from{not_before}
Valid to{not_after}
+ ''' + + # Generate the Subject table + subj_table = ''' +

Subject

+ + + + + + + + + ''' + + for val in cert.subject.rdns: + dn = val.rfc4514_string().split('=') + subj_table += f''' + + + + + ''' + subj_table += ''' + +
Distinguished NameValue
{dn[0]}{dn[1]}
+ ''' + + # Generate the Subject table + iss_table = ''' +

Issuer

+ + + + + + + + + ''' + + for val in cert.issuer.rdns: + dn = val.rfc4514_string().split('=') + iss_table += f''' + + + + + ''' + if 'CN' in dn[0]: + signed_by = dn[1] + iss_table += ''' + +
Distinguished NameValue
{dn[0]}{dn[1]}
+ ''' + + ext_table = None + if cert.extensions: + ext_table = ''' +

Extensions

+ + + + + + + + + ''' + + for extension in cert.extensions: + if isinstance(extension.value, list): + # pylint: disable=W0212 + for extension_value in extension.value: + ext_table += f''' + + + + + ''' + else: + ext_table += f''' + + + + + ''' + ext_table += ''' + +
ExtensionValue
{extension.oid._name}{extension_value.value}
{extension.oid._name}{extension.value}
+ ''' + cert_table = f'\n{cert_table}' + cert_table += f'\n\n{subj_table}' + cert_table += f'\n\n{iss_table}' + if ext_table is not None: + cert_table += f'\n\n{ext_table}' + cert_tables.append(cert_table) + + summary_table += f''' + + {not_after} + {cert_length} + {public_key_type} + {port} + {signed_by} + + ''' + + summary_table += ''' + + + ''' + + html_content += summary_table + '\n'.join('\n' + tables + for tables in cert_tables) + + else: + html_content += (''' +
+
+ No TLS certificates found on the device +
''') + + LOGGER.debug('Module report:\n' + html_content) + + # 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) + + LOGGER.info('Module report generated at: ' + str(report_path)) + return report_path def extract_certificates_from_pcap(self, pcap_files, mac_address): # Initialize a list to store packets diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index fc37ade40..bfa7d3131 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -13,6 +13,7 @@ # limitations under the License. """Module run all the TLS related unit tests""" from tls_util import TLSUtil +from tls_module import TLSModule import os import unittest from common import logger @@ -319,77 +320,71 @@ def security_tls_client_allowed_protocols_test(self): print(str(test_results)) self.assertTrue(test_results[0]) - # Commented out whilst TLS report is recreated - # def tls_module_report_test(self): - # print('\ntls_module_report_test') - # os.environ['DEVICE_MAC'] = '38:d1:35:01:17:fe' - # pcap_file = os.path.join(CAPTURES_DIR, 'tls.pcap') - # tls = TLSModule(module=MODULE, - # log_dir=OUTPUT_DIR, - # conf_file=CONF_FILE, - # results_dir=OUTPUT_DIR, - # startup_capture_file=pcap_file, - # monitor_capture_file=pcap_file, - # tls_capture_file=pcap_file) - # report_out_path = tls.generate_module_report() - - # with open(report_out_path, 'r', encoding='utf-8') as file: - # report_out = file.read() - - # # Read the local good report - # with open(LOCAL_REPORT, 'r', encoding='utf-8') as file: - # report_local = file.read() - - # self.assertEqual(report_out, report_local) - - # Commented out whilst TLS report is recreated - # def tls_module_report_ext_test(self): - # print('\ntls_module_report_ext_test') - # os.environ['DEVICE_MAC'] = '28:29:86:27:d6:05' - # pcap_file = os.path.join(CAPTURES_DIR, 'tls_ext.pcap') - # tls = TLSModule(module=MODULE, - # log_dir=OUTPUT_DIR, - # conf_file=CONF_FILE, - # results_dir=OUTPUT_DIR, - # startup_capture_file=pcap_file, - # monitor_capture_file=pcap_file, - # tls_capture_file=pcap_file) - # report_out_path = tls.generate_module_report() - - # # Read the generated report - # with open(report_out_path, 'r', encoding='utf-8') as file: - # report_out = file.read() - - # # Read the local good report - # with open(LOCAL_REPORT_EXT, 'r', encoding='utf-8') as file: - # report_local = file.read() - - # self.assertEqual(report_out, report_local) - - # Commented out whilst TLS report is recreated - # def tls_module_report_no_cert_test(self): - # print('\ntls_module_report_no_cert_test') - # os.environ['DEVICE_MAC'] = '' - # pcap_file = os.path.join(CAPTURES_DIR, 'tls_ext.pcap') - # tls = TLSModule(module=MODULE, - # log_dir=OUTPUT_DIR, - # conf_file=CONF_FILE, - # results_dir=OUTPUT_DIR, - # startup_capture_file=pcap_file, - # monitor_capture_file=pcap_file, - # tls_capture_file=pcap_file) - - # report_out_path = tls.generate_module_report() - - # # Read the generated report - # with open(report_out_path, 'r', encoding='utf-8') as file: - # report_out = file.read() - - # # Read the local good report - # with open(LOCAL_REPORT_NO_CERT, 'r', encoding='utf-8') as file: - # report_local = file.read() - - # self.assertEqual(report_out, report_local) + def tls_module_report_test(self): + print('\ntls_module_report_test') + os.environ['DEVICE_MAC'] = '38:d1:35:01:17:fe' + pcap_file = os.path.join(CAPTURES_DIR, 'tls.pcap') + tls = TLSModule(module=MODULE, + log_dir=OUTPUT_DIR, + results_dir=OUTPUT_DIR, + startup_capture_file=pcap_file, + monitor_capture_file=pcap_file, + tls_capture_file=pcap_file) + report_out_path = tls.generate_module_report() + + with open(report_out_path, 'r', encoding='utf-8') as file: + report_out = file.read() + + # Read the local good report + with open(LOCAL_REPORT, 'r', encoding='utf-8') as file: + report_local = file.read() + + self.assertEqual(report_out, report_local) + + def tls_module_report_ext_test(self): + print('\ntls_module_report_ext_test') + os.environ['DEVICE_MAC'] = '28:29:86:27:d6:05' + pcap_file = os.path.join(CAPTURES_DIR, 'tls_ext.pcap') + tls = TLSModule(module=MODULE, + log_dir=OUTPUT_DIR, + results_dir=OUTPUT_DIR, + startup_capture_file=pcap_file, + monitor_capture_file=pcap_file, + tls_capture_file=pcap_file) + report_out_path = tls.generate_module_report() + + # Read the generated report + with open(report_out_path, 'r', encoding='utf-8') as file: + report_out = file.read() + + # Read the local good report + with open(LOCAL_REPORT_EXT, 'r', encoding='utf-8') as file: + report_local = file.read() + + self.assertEqual(report_out, report_local) + + def tls_module_report_no_cert_test(self): + print('\ntls_module_report_no_cert_test') + os.environ['DEVICE_MAC'] = '' + pcap_file = os.path.join(CAPTURES_DIR, 'tls_ext.pcap') + tls = TLSModule(module=MODULE, + log_dir=OUTPUT_DIR, + results_dir=OUTPUT_DIR, + startup_capture_file=pcap_file, + monitor_capture_file=pcap_file, + tls_capture_file=pcap_file) + + report_out_path = tls.generate_module_report() + + # Read the generated report + with open(report_out_path, 'r', encoding='utf-8') as file: + report_out = file.read() + + # Read the local good report + with open(LOCAL_REPORT_NO_CERT, 'r', encoding='utf-8') as file: + report_local = file.read() + + self.assertEqual(report_out, report_local) def generate_tls_traffic(self, capture_file, @@ -564,10 +559,10 @@ def download_public_cert(self, hostname, port=443): # Test the results options for tls server tests suite.addTest(TLSModuleTest('security_tls_server_results_test')) - # # Test various report module outputs - # suite.addTest(TLSModuleTest('tls_module_report_test')) - # suite.addTest(TLSModuleTest('tls_module_report_ext_test')) - # suite.addTest(TLSModuleTest('tls_module_report_no_cert_test')) + # Test various report module outputs + suite.addTest(TLSModuleTest('tls_module_report_test')) + suite.addTest(TLSModuleTest('tls_module_report_ext_test')) + suite.addTest(TLSModuleTest('tls_module_report_no_cert_test')) # Test signature validation methods suite.addTest(TLSModuleTest('tls_module_trusted_ca_cert_chain_test')) From 575f1264c6e645593decbaa2eb367b6a8663abcb Mon Sep 17 00:00:00 2001 From: jhughesbiot Date: Wed, 9 Oct 2024 08:59:19 -0600 Subject: [PATCH 02/25] Update extensions processing --- modules/test/tls/python/src/tls_module.py | 56 ++++++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index d28813d4e..cd288b076 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -16,10 +16,13 @@ from tls_util import TLSUtil import os import pyshark +from binascii import hexlify from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa, dsa, ec +from cryptography.x509 import AuthorityKeyIdentifier, SubjectKeyIdentifier, BasicConstraints, KeyUsage +from cryptography.x509 import GeneralNames, DNSName, ExtendedKeyUsage, ObjectIdentifier, SubjectAlternativeName LOG_NAME = 'test_tls' MODULE_REPORT_FILE_NAME = 'tls_report.html' @@ -211,14 +214,14 @@ def generate_module_report(self): ext_table += f''' {extension.oid._name} - {extension_value.value} + {self.format_extension_value(extension_value.value)} ''' else: ext_table += f''' {extension.oid._name} - {extension.value} + {self.format_extension_value(extension.value)} ''' ext_table += ''' @@ -269,6 +272,55 @@ def generate_module_report(self): LOGGER.info('Module report generated at: ' + str(report_path)) return report_path + def format_extension_value(self, value): + if isinstance(value, bytes): + # Convert byte sequences to hex strings + return hexlify(value).decode() + elif isinstance(value, (list, tuple)): + # Format lists/tuples for HTML output + return ', '.join([self.format_extension_value(v) for v in value]) + elif isinstance(value, ExtendedKeyUsage): + # Handle ExtendedKeyUsage extension + return ', '.join( + [oid._name or f'Unknown OID ({oid.dotted_string})' for oid in value]) + elif isinstance(value, GeneralNames): + # Handle GeneralNames (used in SubjectAlternativeName) + return ', '.join( + [name.value for name in value if isinstance(name, DNSName)]) + elif isinstance(value, SubjectAlternativeName): + # Extract and format the GeneralNames (which contains DNSName, + #IPAddress, etc.) + return self.format_extension_value(value.get_values_for_type(DNSName)) + + elif isinstance(value, ObjectIdentifier): + # Handle ObjectIdentifier directly + return value._name or f'Unknown OID ({value.dotted_string})' + elif hasattr(value, '_name'): + # Extract the name for OIDs (Object Identifiers) + return value._name + elif isinstance(value, AuthorityKeyIdentifier): + # Handle AuthorityKeyIdentifier extension + key_id = self.format_extension_value(value.key_identifier) + cert_issuer = value.authority_cert_issuer + cert_serial = value.authority_cert_serial_number + + return (f'key_identifier={key_id}, ' + f'authority_cert_issuer={cert_issuer}, ' + f'authority_cert_serial_number={cert_serial}') + elif isinstance(value, SubjectKeyIdentifier): + # Handle SubjectKeyIdentifier extension + return f'digest={self.format_extension_value(value.digest)}' + elif isinstance(value, BasicConstraints): + # Handle BasicConstraints extension + return f'ca={value.ca}, path_length={value.path_length}' + elif isinstance(value, KeyUsage): + # Handle KeyUsage extension + return (f'digital_signature={value.digital_signature}, ' + f'key_cert_sign={value.key_cert_sign}, ' + f'key_encipherment={value.key_encipherment}, ' + f'crl_sign={value.crl_sign}') + return str(value) # Fallback to string conversion + def extract_certificates_from_pcap(self, pcap_files, mac_address): # Initialize a list to store packets all_packets = [] From a9460921baf088405b685f5181030234e507c79c Mon Sep 17 00:00:00 2001 From: jhughesbiot Date: Wed, 9 Oct 2024 09:20:44 -0600 Subject: [PATCH 03/25] pylint --- modules/test/tls/python/src/tls_module.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index cd288b076..db57154e6 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. """TLS test module""" +# pylint: disable=W0212 + from test_module import TestModule from tls_util import TLSUtil import os @@ -84,14 +86,14 @@ def generate_module_report(self): ''' cert_tables = [] - for cert_num, ((ip_address, port), + for cert_num, ((ip_address, port), # pylint: disable=W0612 cert) in enumerate(certificates.items()): # Extract certificate data not_valid_before = cert.not_valid_before not_valid_after = cert.not_valid_after version_value = f'{cert.version.value + 1} ({hex(cert.version.value)})' - signature_alg_value = cert.signature_algorithm_oid._name # pylint: disable=W0212 + signature_alg_value = cert.signature_algorithm_oid._name not_before = str(not_valid_before) not_after = str(not_valid_after) public_key = cert.public_key() @@ -209,7 +211,6 @@ def generate_module_report(self): for extension in cert.extensions: if isinstance(extension.value, list): - # pylint: disable=W0212 for extension_value in extension.value: ext_table += f''' From 8025ddce582210ba31abf26e5b3f8367aa76a78d Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 18 Oct 2024 15:41:07 +0100 Subject: [PATCH 04/25] Change HTML report in unit test --- .../tls/reports/tls_report_ext_local.html | 129 ++++++++++++++++ .../unit/tls/reports/tls_report_ext_local.md | 33 ---- .../unit/tls/reports/tls_report_local.html | 144 ++++++++++++++++++ testing/unit/tls/reports/tls_report_local.md | 35 ----- .../tls/reports/tls_report_no_cert_local.html | 5 + .../tls/reports/tls_report_no_cert_local.md | 9 -- testing/unit/tls/tls_module_test.py | 7 +- 7 files changed, 282 insertions(+), 80 deletions(-) create mode 100644 testing/unit/tls/reports/tls_report_ext_local.html delete mode 100644 testing/unit/tls/reports/tls_report_ext_local.md create mode 100644 testing/unit/tls/reports/tls_report_local.html delete mode 100644 testing/unit/tls/reports/tls_report_local.md create mode 100644 testing/unit/tls/reports/tls_report_no_cert_local.html delete mode 100644 testing/unit/tls/reports/tls_report_no_cert_local.md diff --git a/testing/unit/tls/reports/tls_report_ext_local.html b/testing/unit/tls/reports/tls_report_ext_local.html new file mode 100644 index 000000000..c14e61d93 --- /dev/null +++ b/testing/unit/tls/reports/tls_report_ext_local.html @@ -0,0 +1,129 @@ +

TLS Module

+ + + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2027-07-25 15:33:09888EC443Sub CA
+ + + +

Certificate

+ + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version3 (0x2)
Signature Alg.sha256WithRSAEncryption
Validity from2022-07-26 15:33:09
Valid to2027-07-25 15:33:09
+ + + +

Subject

+ + + + + + + + + + + + + + + + + + + + +
Distinguished NameValue
CUS
CNapc27D605.nam.gad.schneider-electric.com
+ + + +

Issuer

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Distinguished NameValue
CUS
OIT Division
CNSub CA
+ + + +

Extensions

+ + + + + + + + + + + + + + + +
ExtensionValue
subjectAltNameap9643_qa1941270129.nam.gad.schneider-electric.com
+ diff --git a/testing/unit/tls/reports/tls_report_ext_local.md b/testing/unit/tls/reports/tls_report_ext_local.md deleted file mode 100644 index 878fa0743..000000000 --- a/testing/unit/tls/reports/tls_report_ext_local.md +++ /dev/null @@ -1,33 +0,0 @@ -# TLS Module - -### Certificate -| Property | Value | -|---|---| -| Version | 3 (0x2) | -| Signature Alg. | sha256WithRSAEncryption | -| Validity from | 2022-07-26 15:33:09 | -| Valid to | 2027-07-25 15:33:09 | - -### Subject -| Distinguished Name | Value | -|---|---| -| C | US -| CN | apc27D605.nam.gad.schneider-electric.com - -### Issuer -| Distinguished Name | Value | -|---|---| -| C | US -| O | IT Division -| CN | Sub CA - -### Extensions -| Extension | Value | -|---|---| -| subjectAltName | ap9643_qa1941270129.nam.gad.schneider-electric.com - -## Summary - -| # | Expiry | Length | Type | Port No. | Signed by | -|-------|---------------------------|----------|--------|------------|-------------| -| 1 | 2027-07-25 15:33:09 | 888 | EC | 443 | Sub CA | \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_local.html b/testing/unit/tls/reports/tls_report_local.html new file mode 100644 index 000000000..6cabc837b --- /dev/null +++ b/testing/unit/tls/reports/tls_report_local.html @@ -0,0 +1,144 @@ +

TLS Module

+ + + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2027-09-21 19:57:57901RSA443BuildingsIoT RSA Signing CA
+ + + +

Certificate

+ + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version1 (0x0)
Signature Alg.sha256WithRSAEncryption
Validity from2022-09-21 19:57:57
Valid to2027-09-21 19:57:57
+ + + +

Subject

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Distinguished NameValue
CUS
STCalifornia
LConcord
OBuildingsIoT
OUSoftware
CNEasyIO_FS-32
+ + + +

Issuer

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Distinguished NameValue
CUS
STCalifornia
LConcord
OBuildingsIoT
OUSoftware
CNBuildingsIoT RSA Signing CA
+ diff --git a/testing/unit/tls/reports/tls_report_local.md b/testing/unit/tls/reports/tls_report_local.md deleted file mode 100644 index dc3866dc6..000000000 --- a/testing/unit/tls/reports/tls_report_local.md +++ /dev/null @@ -1,35 +0,0 @@ -# TLS Module - -### Certificate -| Property | Value | -|---|---| -| Version | 1 (0x0) | -| Signature Alg. | sha256WithRSAEncryption | -| Validity from | 2022-09-21 19:57:57 | -| Valid to | 2027-09-21 19:57:57 | - -### Subject -| Distinguished Name | Value | -|---|---| -| C | US -| ST | California -| L | Concord -| O | BuildingsIoT -| OU | Software -| CN | EasyIO_FS-32 - -### Issuer -| Distinguished Name | Value | -|---|---| -| C | US -| ST | California -| L | Concord -| O | BuildingsIoT -| OU | Software -| CN | BuildingsIoT RSA Signing CA - -## Summary - -| # | Expiry | Length | Type | Port No. | Signed by | -|-------|---------------------------|----------|--------|------------|-------------| -| 1 | 2027-09-21 19:57:57 | 901 | RSA | 443 | BuildingsIoT RSA Signing CA | \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_no_cert_local.html b/testing/unit/tls/reports/tls_report_no_cert_local.html new file mode 100644 index 000000000..34797e200 --- /dev/null +++ b/testing/unit/tls/reports/tls_report_no_cert_local.html @@ -0,0 +1,5 @@ +

TLS Module

+
+
+ No TLS certificates found on the device +
diff --git a/testing/unit/tls/reports/tls_report_no_cert_local.md b/testing/unit/tls/reports/tls_report_no_cert_local.md deleted file mode 100644 index 6de5bb88a..000000000 --- a/testing/unit/tls/reports/tls_report_no_cert_local.md +++ /dev/null @@ -1,9 +0,0 @@ -# TLS Module - -- No device certificates detected - - -## Summary - -| # | Expiry | Length | Type | Port No. | Signed by | -|-------|---------------------------|----------|--------|------------|-------------| \ No newline at end of file diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index bfa7d3131..9f4fee390 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -39,9 +39,10 @@ CERT_DIR = os.path.join(TEST_FILES_DIR, 'certs/') ROOT_CERTS_DIR = os.path.join(TEST_FILES_DIR, 'root_certs') -LOCAL_REPORT = os.path.join(REPORTS_DIR, 'tls_report_local.md') -LOCAL_REPORT_EXT = os.path.join(REPORTS_DIR, 'tls_report_ext_local.md') -LOCAL_REPORT_NO_CERT = os.path.join(REPORTS_DIR, 'tls_report_no_cert_local.md') +LOCAL_REPORT = os.path.join(REPORTS_DIR, 'tls_report_local.html') +LOCAL_REPORT_EXT = os.path.join(REPORTS_DIR, 'tls_report_ext_local.html') +LOCAL_REPORT_NO_CERT = os.path.join(REPORTS_DIR, + 'tls_report_no_cert_local.html') CONF_FILE = 'modules/test/' + MODULE + '/conf/module_config.json' INTERNET_IFACE = 'eth0' From 52b2423654d62ffe6c814190fbac2479084853d0 Mon Sep 17 00:00:00 2001 From: Marius <86727846+MariusBaldovin@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:23:20 +0100 Subject: [PATCH 05/25] fixed the failing unit tests (#905) --- testing/unit/tls/reports/tls_report_ext_local.html | 2 +- testing/unit/tls/reports/tls_report_local.html | 2 +- .../unit/tls/reports/tls_report_no_cert_local.html | 2 +- testing/unit/tls/tls_module_test.py | 11 ++++++++++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/testing/unit/tls/reports/tls_report_ext_local.html b/testing/unit/tls/reports/tls_report_ext_local.html index c14e61d93..142e3a7f1 100644 --- a/testing/unit/tls/reports/tls_report_ext_local.html +++ b/testing/unit/tls/reports/tls_report_ext_local.html @@ -126,4 +126,4 @@

Extensions

- + \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_local.html b/testing/unit/tls/reports/tls_report_local.html index 6cabc837b..36b20198e 100644 --- a/testing/unit/tls/reports/tls_report_local.html +++ b/testing/unit/tls/reports/tls_report_local.html @@ -141,4 +141,4 @@

Issuer

- + \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_no_cert_local.html b/testing/unit/tls/reports/tls_report_no_cert_local.html index 34797e200..de2825e41 100644 --- a/testing/unit/tls/reports/tls_report_no_cert_local.html +++ b/testing/unit/tls/reports/tls_report_no_cert_local.html @@ -2,4 +2,4 @@

TLS Module

No TLS certificates found on the device -
+ \ No newline at end of file diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index 9f4fee390..6d8c0b1c0 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -332,7 +332,6 @@ def tls_module_report_test(self): monitor_capture_file=pcap_file, tls_capture_file=pcap_file) report_out_path = tls.generate_module_report() - with open(report_out_path, 'r', encoding='utf-8') as file: report_out = file.read() @@ -362,6 +361,11 @@ def tls_module_report_ext_test(self): with open(LOCAL_REPORT_EXT, 'r', encoding='utf-8') as file: report_local = file.read() + # Copy the generated html report to a new file + new_report_name = 'tls_report_ext_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) def tls_module_report_no_cert_test(self): @@ -385,6 +389,11 @@ def tls_module_report_no_cert_test(self): with open(LOCAL_REPORT_NO_CERT, 'r', encoding='utf-8') as file: report_local = file.read() + # Copy the generated html report to a new file + new_report_name = 'tls_report_no_cert_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) def generate_tls_traffic(self, From 9ca6dba0f92eda2ce76e83664c7ab57f1cbab3dd Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Mon, 21 Oct 2024 12:06:28 +0100 Subject: [PATCH 06/25] Modify report design --- framework/python/src/common/util.py | 4 +- framework/python/src/net_orc/ip_control.py | 2 +- modules/test/ntp/python/src/ntp_module.py | 2 +- modules/test/tls/python/src/tls_module.py | 202 ++++++++++----------- 4 files changed, 102 insertions(+), 108 deletions(-) diff --git a/framework/python/src/common/util.py b/framework/python/src/common/util.py index ba1b23e81..7bb7ea73f 100644 --- a/framework/python/src/common/util.py +++ b/framework/python/src/common/util.py @@ -24,7 +24,7 @@ LOGGER = logger.get_logger('util') -def run_command(cmd, output=True, timeout=None): +def run_command(cmd, output=True, timeout=None, supress_error=False): """Runs a process at the os level By default, returns the standard output and error output If the caller sets optional output parameter to False, @@ -38,7 +38,7 @@ def run_command(cmd, output=True, timeout=None): stderr=subprocess.PIPE) as process: stdout, stderr = process.communicate(timeout) - if process.returncode != 0 and output: + if process.returncode != 0 and output and not supress_error: err_msg = f'{stderr.strip()}. Code: {process.returncode}' LOGGER.error('Command failed: ' + cmd) LOGGER.error('Error: ' + err_msg) diff --git a/framework/python/src/net_orc/ip_control.py b/framework/python/src/net_orc/ip_control.py index aa07283af..73a6aceeb 100644 --- a/framework/python/src/net_orc/ip_control.py +++ b/framework/python/src/net_orc/ip_control.py @@ -259,7 +259,7 @@ def configure_container_interface(self, def ping_via_gateway(self, host): """Ping the host trough the gateway container""" command = f'timeout 3 docker exec tr-ct-gateway ping -W 1 -c 1 {host}' - output = util.run_command(command) + output = util.run_command(command, supress_error=True) if '0% packet loss' in output[0]: return True return False diff --git a/modules/test/ntp/python/src/ntp_module.py b/modules/test/ntp/python/src/ntp_module.py index f82240ff1..eb0e81423 100644 --- a/modules/test/ntp/python/src/ntp_module.py +++ b/modules/test/ntp/python/src/ntp_module.py @@ -120,7 +120,7 @@ def generate_module_report(self): if total_requests + total_responses > 0: table_content = ''' - +
TLS Module' # List of capture files to scan pcap_files = [ @@ -68,27 +68,39 @@ def generate_module_report(self): ] certificates = self.extract_certificates_from_pcap(pcap_files, self._device_mac) - if len(certificates) > 0: - # Add summary table - summary_table = ''' -
- - - - - - - - - - - ''' + if len(certificates) > 0: cert_tables = [] for cert_num, ((ip_address, port), # pylint: disable=W0612 cert) in enumerate(certificates.items()): + # Add summary table + summary_table = ''' +
ExpiryLengthTypePort numberSigned by
+ + + + + + + + + + + ''' + + # Generate the certificate table + cert_table = ''' +
ExpiryLengthTypePort numberSigned by
+ + + + + + + ''' + # Extract certificate data not_valid_before = cert.not_valid_before not_valid_after = cert.not_valid_after @@ -98,6 +110,7 @@ def generate_module_report(self): not_after = str(not_valid_after) public_key = cert.public_key() signed_by = 'None' + if isinstance(public_key, rsa.RSAPublicKey): public_key_type = 'RSA' elif isinstance(public_key, dsa.DSAPublicKey): @@ -106,108 +119,78 @@ def generate_module_report(self): public_key_type = 'EC' else: public_key_type = 'Unknown' + # Calculate certificate length cert_length = len( cert.public_bytes(encoding=serialization.Encoding.DER)) - # Generate the Certificate table - cert_table = f''' -

Certificate

-
PropertyValue
- - - - - - - - - - - - - - - - - - - - - - - - -
PropertyValue
Version{version_value}
Signature Alg.{signature_alg_value}
Validity from{not_before}
Valid to{not_after}
+ # Append certification information + cert_table += f''' + + Version + {version_value} + + + Signature Alg. + {signature_alg_value} + + + Validity from + {not_before} + + + Valid to + {not_after} + + + ''' - # Generate the Subject table - subj_table = ''' -

Subject

+ subject_table = ''' - + - - ''' + ''' + # Append the subject information for val in cert.subject.rdns: dn = val.rfc4514_string().split('=') - subj_table += f''' + subject_table += f''' ''' - subj_table += ''' - -
Distinguished NameProperty Value
{dn[0]} {dn[1]}
- ''' - # Generate the Subject table - iss_table = ''' -

Issuer

- - - - - - - - - ''' + subject_table += ''' + +
Distinguished NameValue
''' + # Append issuer information for val in cert.issuer.rdns: dn = val.rfc4514_string().split('=') - iss_table += f''' - - {dn[0]} - {dn[1]} - - ''' if 'CN' in dn[0]: signed_by = dn[1] - iss_table += ''' - - - ''' - ext_table = None + ext_table = '' + + # Append extensions information if cert.extensions: + ext_table = ''' -

Extensions

+
Certificate Extensions
- - - - - - - - ''' + + + + + + + ''' for extension in cert.extensions: if isinstance(extension.value, list): @@ -225,17 +208,12 @@ def generate_module_report(self): ''' + ext_table += ''' - -
ExtensionValue
PropertyValue
{self.format_extension_value(extension.value)}
- ''' - cert_table = f'\n{cert_table}' - cert_table += f'\n\n{subj_table}' - cert_table += f'\n\n{iss_table}' - if ext_table is not None: - cert_table += f'\n\n{ext_table}' - cert_tables.append(cert_table) + + ''' + # Add summary table row summary_table += f''' {not_after} @@ -244,15 +222,31 @@ def generate_module_report(self): {port} {signed_by} - ''' + + + ''' - summary_table += ''' - - - ''' + # Merge all table HTML + summary_table = f'\n{summary_table}' + + summary_table += f''' +
+
+
Certificate Information
+ {cert_table} +
+
+
Subject Information
+ {subject_table} +
+
''' + + if ext_table is not None: + summary_table += f'\n\n{ext_table}' + + cert_tables.append(summary_table) - html_content += summary_table + '\n'.join('\n' + tables - for tables in cert_tables) + html_content += '\n'.join('\n' + tables for tables in cert_tables) else: html_content += (''' From 099a0370147459fe999c323b8ad316883d3f3f0e Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Mon, 21 Oct 2024 13:24:03 +0100 Subject: [PATCH 07/25] Fix unit testing --- modules/test/ntp/python/src/ntp_module.py | 2 +- testing/unit/ntp/ntp_module_test.py | 11 ++ .../unit/ntp/reports/ntp_report_local.html | 2 +- .../tls/reports/tls_report_ext_local.html | 139 +++++++----------- .../unit/tls/reports/tls_report_local.html | 133 ++++++----------- .../tls/reports/tls_report_no_cert_local.html | 2 +- testing/unit/tls/tls_module_test.py | 12 +- 7 files changed, 122 insertions(+), 179 deletions(-) diff --git a/modules/test/ntp/python/src/ntp_module.py b/modules/test/ntp/python/src/ntp_module.py index eb0e81423..1bbc9c04a 100644 --- a/modules/test/ntp/python/src/ntp_module.py +++ b/modules/test/ntp/python/src/ntp_module.py @@ -120,7 +120,7 @@ def generate_module_report(self): if total_requests + total_responses > 0: table_content = ''' - diff --git a/testing/unit/ntp/ntp_module_test.py b/testing/unit/ntp/ntp_module_test.py index af74722f1..96394c198 100644 --- a/testing/unit/ntp/ntp_module_test.py +++ b/testing/unit/ntp/ntp_module_test.py @@ -16,6 +16,7 @@ import unittest from scapy.all import rdpcap, NTP, wrpcap import os +import shutil import sys MODULE = 'ntp' @@ -63,6 +64,11 @@ def ntp_module_report_test(self): with open(LOCAL_REPORT, 'r', encoding='utf-8') as file: report_local = file.read() + # Copy the generated html report to a new file + 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 @@ -112,6 +118,11 @@ def ntp_module_report_no_ntp_test(self): with open(LOCAL_REPORT_NO_NTP, 'r', encoding='utf-8') as file: report_local = file.read() + # Copy the generated html report to a new file + new_report_name = 'ntp_no_ntp.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) if __name__ == '__main__': diff --git a/testing/unit/ntp/reports/ntp_report_local.html b/testing/unit/ntp/reports/ntp_report_local.html index 025881db5..1fe5e3f3a 100644 --- a/testing/unit/ntp/reports/ntp_report_local.html +++ b/testing/unit/ntp/reports/ntp_report_local.html @@ -18,7 +18,7 @@

NTP Module

Source
- +
diff --git a/testing/unit/tls/reports/tls_report_ext_local.html b/testing/unit/tls/reports/tls_report_ext_local.html index 142e3a7f1..bf8193391 100644 --- a/testing/unit/tls/reports/tls_report_ext_local.html +++ b/testing/unit/tls/reports/tls_report_ext_local.html @@ -1,129 +1,100 @@ -

TLS Module

-
Source
- - - - - - - - - - - - - - - - - - - - -
ExpiryLengthTypePort numberSigned by
2027-07-25 15:33:09888EC443Sub CA
- +

TLS Module

-

Certificate

- +
- - + + + + + + - - - - - - - - - - - - - + + + +
PropertyValueExpiryLengthTypePort numberSigned by
Version3 (0x2)
Signature Alg.sha256WithRSAEncryption
Validity from2022-07-26 15:33:09
Valid to 2027-07-25 15:33:09888EC443Sub CA
- - -

Subject

+
+
+
Certificate Information
+ - + + + + + + + + + + + + + + + + + + +
Distinguished NameProperty Value
Version3 (0x2)
Signature Alg.sha256WithRSAEncryption
Validity from2022-07-26 15:33:09
Valid to2027-07-25 15:33:09
- - C - US - - - - CN - apc27D605.nam.gad.schneider-electric.com - - - - - - - -

Issuer

+
+
+
Subject Information
+ - + - - - - - - - + - -
Distinguished NameProperty Value
C US
OIT Division
CNSub CAapc27D605.nam.gad.schneider-electric.com
- + + +
+
-

Extensions

+
Certificate Extensions
- - - - - - - - + + + + + + + - -
ExtensionValue
PropertyValue
subjectAltName ap9643_qa1941270129.nam.gad.schneider-electric.com
- \ No newline at end of file + + \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_local.html b/testing/unit/tls/reports/tls_report_local.html index 36b20198e..beef934d3 100644 --- a/testing/unit/tls/reports/tls_report_local.html +++ b/testing/unit/tls/reports/tls_report_local.html @@ -1,114 +1,71 @@ -

TLS Module

- - - - - - - - - - - - - - - - - - - - - -
ExpiryLengthTypePort numberSigned by
2027-09-21 19:57:57901RSA443BuildingsIoT RSA Signing CA
- +

TLS Module

-

Certificate

- +
- - + + + + + + - - - - - - - - - - - - - + + + +
PropertyValueExpiryLengthTypePort numberSigned by
Version1 (0x0)
Signature Alg.sha256WithRSAEncryption
Validity from2022-09-21 19:57:57
Valid to 2027-09-21 19:57:57901RSA443BuildingsIoT RSA Signing CA
- - -

Subject

+
+
+
Certificate Information
+ - + + + + + + + + + + + + + + + + + + +
Distinguished NameProperty Value
Version1 (0x0)
Signature Alg.sha256WithRSAEncryption
Validity from2022-09-21 19:57:57
Valid to2027-09-21 19:57:57
- - C - US - - - - ST - California - - - - L - Concord - - - - O - BuildingsIoT - - - - OU - Software - - - - CN - EasyIO_FS-32 - - - - - - - -

Issuer

+
+
+
Subject Information
+ - + - @@ -136,9 +93,11 @@

Issuer

- + - -
Distinguished NameProperty Value
C US
CNBuildingsIoT RSA Signing CAEasyIO_FS-32
- \ No newline at end of file + + +
+
+ diff --git a/testing/unit/tls/reports/tls_report_no_cert_local.html b/testing/unit/tls/reports/tls_report_no_cert_local.html index de2825e41..c025ee9e8 100644 --- a/testing/unit/tls/reports/tls_report_no_cert_local.html +++ b/testing/unit/tls/reports/tls_report_no_cert_local.html @@ -1,4 +1,4 @@ -

TLS Module

+

TLS Module

No TLS certificates found on the device diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index 6d8c0b1c0..8e7b4d5c1 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -545,6 +545,7 @@ def download_public_cert(self, hostname, port=443): if __name__ == '__main__': suite = unittest.TestSuite() suite.addTest(TLSModuleTest('client_hello_packets_test')) + # TLS 1.2 server tests suite.addTest(TLSModuleTest('security_tls_v1_2_server_test')) suite.addTest(TLSModuleTest('security_tls_v1_2_for_1_3_server_test')) @@ -558,6 +559,7 @@ def download_public_cert(self, hostname, port=443): # # TLS 1.3 server tests suite.addTest(TLSModuleTest('security_tls_v1_3_server_test')) + # TLS client tests suite.addTest(TLSModuleTest('security_tls_v1_2_client_test')) suite.addTest(TLSModuleTest('security_tls_v1_3_client_test')) @@ -574,12 +576,12 @@ def download_public_cert(self, hostname, port=443): suite.addTest(TLSModuleTest('tls_module_report_ext_test')) suite.addTest(TLSModuleTest('tls_module_report_no_cert_test')) - # Test signature validation methods - suite.addTest(TLSModuleTest('tls_module_trusted_ca_cert_chain_test')) - suite.addTest(TLSModuleTest('tls_module_local_ca_cert_test')) - suite.addTest(TLSModuleTest('tls_module_ca_cert_spaces_test')) + # # Test signature validation methods + # suite.addTest(TLSModuleTest('tls_module_trusted_ca_cert_chain_test')) + # suite.addTest(TLSModuleTest('tls_module_local_ca_cert_test')) + # suite.addTest(TLSModuleTest('tls_module_ca_cert_spaces_test')) - suite.addTest(TLSModuleTest('security_tls_client_allowed_protocols_test')) + # suite.addTest(TLSModuleTest('security_tls_client_allowed_protocols_test')) runner = unittest.TextTestRunner() test_result = runner.run(suite) From d2deaaea87bcd3efe1f6fd2b417c103b39764e07 Mon Sep 17 00:00:00 2001 From: jhughesbiot Date: Mon, 28 Oct 2024 11:27:14 -0600 Subject: [PATCH 08/25] Feature/report outbound connections (#877) * Add methods to generate table of all outbound connection ips * pylint * Add outbound connections to report Add port to table --------- Signed-off-by: J Boddey Co-authored-by: J Boddey --- modules/test/tls/python/src/tls_module.py | 42 ++++++++++++++++++-- modules/test/tls/python/src/tls_util.py | 47 +++++++++++++++++++++++ testing/unit/tls/tls_module_test.py | 27 ++++++++++++- 3 files changed, 112 insertions(+), 4 deletions(-) diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index b027bc635..c543eee1e 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -72,8 +72,10 @@ def generate_module_report(self): if len(certificates) > 0: cert_tables = [] - for cert_num, ((ip_address, port), # pylint: disable=W0612 - cert) in enumerate(certificates.items()): + # pylint: disable=W0612 + for cert_num, ( + (ip_address, port), + cert) in enumerate(certificates.items()): # Add summary table summary_table = ''' @@ -246,7 +248,13 @@ def generate_module_report(self): cert_tables.append(summary_table) - html_content += '\n'.join('\n' + tables for tables in cert_tables) + outbound_conns = self._tls_util.get_all_outbound_connections( + device_mac=self._device_mac, capture_files=pcap_files) + conn_table = self.generate_outbound_connection_table(outbound_conns) + + html_content += summary_table + '\n'.join('\n' + tables + for tables in cert_tables) + html_content += conn_table else: html_content += (''' @@ -316,6 +324,34 @@ def format_extension_value(self, value): f'crl_sign={value.crl_sign}') return str(value) # Fallback to string conversion + def generate_outbound_connection_table(self, outbound_conns): + """Generate just an HTML table from a list of IPs""" + html_content = ''' +

Outbound Connections

+ + + + + + + + + ''' + + rows = [ + f'\t' + for ip, port in outbound_conns + ] + html_content += '\n'.join(rows) + + # Close the table + html_content += """ + + \r
Destination IPPort
{ip}{port}
+ """ + + return html_content + def extract_certificates_from_pcap(self, pcap_files, mac_address): # Initialize a list to store packets all_packets = [] diff --git a/modules/test/tls/python/src/tls_util.py b/modules/test/tls/python/src/tls_util.py index 9f00b96ef..1554eba8d 100644 --- a/modules/test/tls/python/src/tls_util.py +++ b/modules/test/tls/python/src/tls_util.py @@ -25,6 +25,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from ipaddress import IPv4Address +from scapy.all import rdpcap, IP, Ether, TCP, UDP LOG_NAME = 'tls_util' LOGGER = None @@ -37,6 +38,7 @@ ipaddress.ip_network('172.16.0.0/12'), ipaddress.ip_network('192.168.0.0/16') ] +TR_CONTAINER_MAC_PREFIX = '9a:02:57:1e:8f:' #Define the allowed protocols as tshark filters DEFAULT_ALLOWED_PROTOCOLS = ['quic'] @@ -59,6 +61,51 @@ def __init__(self, if allowed_protocols is None: self._allowed_protocols = DEFAULT_ALLOWED_PROTOCOLS + def get_all_outbound_connections(self, device_mac, capture_files): + """Process multiple pcap files and combine unique IP destinations.""" + + outbound_conns = set() + for capture in capture_files: + ips = self.get_outbound_connections(device_mac=device_mac, + capture_file=capture) + outbound_conns.update(ips) + return list(outbound_conns) + + def get_outbound_connections(self, device_mac, capture_file): + """Extract unique IP and port destinations from a single pcap file + based on the known MAC address.""" + packets = rdpcap(capture_file) + outbound_conns = set() + for packet in packets: + if Ether in packet and IP in packet: + if packet[Ether].src == device_mac: + ip_dst = packet[IP].dst + port_dst = 'Unknown' + + # Check if the packet has TCP or UDP layer to get the destination port + if TCP in packet: + port_dst = packet[TCP].dport + elif UDP in packet: + port_dst = packet[UDP].dport + + if self.is_external_ip(ip_dst): + outbound_conns.add((ip_dst, port_dst)) + + return outbound_conns + + def is_external_ip(self, ip): + """Check if the IP is an external (non-private) IP address.""" + try: + # Convert the IP string into an IPv4Address object + ip_addr = ipaddress.ip_address(ip) + + # Return True only if the IP is not in a private or reserved range + return not (ip_addr.is_private or ip_addr.is_loopback + or ip_addr.is_link_local) + except ValueError: + # Return False if the IP is invalid or not IPv4 + return False + def get_public_certificate(self, host, port=443, diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index 8e7b4d5c1..8b01bd75a 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. """Module run all the TLS related unit tests""" -from tls_util import TLSUtil from tls_module import TLSModule +from tls_util import TLSUtil import os import unittest from common import logger @@ -321,6 +321,28 @@ def security_tls_client_allowed_protocols_test(self): print(str(test_results)) self.assertTrue(test_results[0]) + def outbound_connections_test(self): + """ Test generation of the outbound connection ips""" + print('\noutbound_connections_test') + capture_file = os.path.join(CAPTURES_DIR, 'monitor.pcap') + ip_dst = TLS_UTIL.get_all_outbound_connections( + device_mac='70:b3:d5:96:c0:00', capture_files=[capture_file]) + print(str(ip_dst)) + # Compare as sets since returned order is not guaranteed + self.assertEqual( + set(ip_dst), + set(['8.8.8.8', '224.0.0.22', '18.140.82.197', '216.239.35.0'])) + + def outbound_connections_report_test(self): + """ Test generation of the outbound connection ips""" + print('\noutbound_connections_report_test') + capture_file = os.path.join(CAPTURES_DIR, 'monitor.pcap') + ip_dst = TLS_UTIL.get_all_outbound_connections( + device_mac='70:b3:d5:96:c0:00', capture_files=[capture_file]) + tls = TLSModule(module=MODULE) + gen_html = tls.generate_outbound_connection_table(ip_dst) + print(gen_html) + def tls_module_report_test(self): print('\ntls_module_report_test') os.environ['DEVICE_MAC'] = '38:d1:35:01:17:fe' @@ -583,6 +605,9 @@ def download_public_cert(self, hostname, port=443): # suite.addTest(TLSModuleTest('security_tls_client_allowed_protocols_test')) + suite.addTest(TLSModuleTest('outbound_connections_test')) + suite.addTest(TLSModuleTest('outbound_connections_report_test')) + runner = unittest.TextTestRunner() test_result = runner.run(suite) From d0d720b8be620353329ac35809616963ef4cd562 Mon Sep 17 00:00:00 2001 From: jhughesbiot Date: Mon, 28 Oct 2024 16:18:50 -0600 Subject: [PATCH 09/25] Add sorting to report info Add/update unit tests --- modules/test/tls/python/src/tls_module.py | 9 +- modules/test/tls/python/src/tls_util.py | 24 +- testing/unit/report/report_test.py | 1 + .../unit/tls/captures/multi_page_monitor.pcap | Bin 0 -> 284634 bytes .../unit/tls/captures/multi_page_startup.pcap | Bin 0 -> 11129 bytes testing/unit/tls/captures/multi_page_tls.pcap | Bin 0 -> 235069 bytes .../unit/tls/reports/tls_report_local.html | 462 +++++++++++++++++- .../tls/reports/tls_report_local_single.html | 103 ++++ testing/unit/tls/tls_module_test.py | 38 +- 9 files changed, 604 insertions(+), 33 deletions(-) create mode 100644 testing/unit/tls/captures/multi_page_monitor.pcap create mode 100644 testing/unit/tls/captures/multi_page_startup.pcap create mode 100644 testing/unit/tls/captures/multi_page_tls.pcap create mode 100644 testing/unit/tls/reports/tls_report_local_single.html diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index c543eee1e..f7d7ccc10 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -73,9 +73,8 @@ def generate_module_report(self): cert_tables = [] # pylint: disable=W0612 - for cert_num, ( - (ip_address, port), - cert) in enumerate(certificates.items()): + for cert_num, ((ip_address, port), + cert) in enumerate(certificates.items()): # Add summary table summary_table = ''' @@ -385,7 +384,9 @@ def extract_certificates_from_pcap(self, pcap_files, mac_address): port = packet.tcp.srcport if 'tcp' in packet else packet.udp.srcport # Store certificate in dictionary with IP address and port as key certificates[(ip_address, port)] = certificate - return certificates + sorted_keys = sorted(certificates.keys(), key=lambda x: (x[0], x[1])) + sorted_certificates = {k: certificates[k] for k in sorted_keys} + return sorted_certificates def _security_tls_v1_2_server(self): LOGGER.info('Running security.tls.v1_2_server') diff --git a/modules/test/tls/python/src/tls_util.py b/modules/test/tls/python/src/tls_util.py index 1554eba8d..1557b61f2 100644 --- a/modules/test/tls/python/src/tls_util.py +++ b/modules/test/tls/python/src/tls_util.py @@ -62,20 +62,25 @@ def __init__(self, self._allowed_protocols = DEFAULT_ALLOWED_PROTOCOLS def get_all_outbound_connections(self, device_mac, capture_files): - """Process multiple pcap files and combine unique IP destinations.""" + """Process multiple pcap files and combine unique IP destinations in the + order of first appearance.""" - outbound_conns = set() + all_outbound_conns = [] for capture in capture_files: ips = self.get_outbound_connections(device_mac=device_mac, capture_file=capture) - outbound_conns.update(ips) - return list(outbound_conns) + all_outbound_conns.extend(ips) # Collect all connections sequentially + + # Remove duplicates while preserving the first-seen order + unique_ordered_conns = list(dict.fromkeys(all_outbound_conns)) + return unique_ordered_conns def get_outbound_connections(self, device_mac, capture_file): """Extract unique IP and port destinations from a single pcap file - based on the known MAC address.""" + based on the known MAC address, preserving the order of appearance.""" packets = rdpcap(capture_file) - outbound_conns = set() + outbound_conns = [] + for packet in packets: if Ether in packet and IP in packet: if packet[Ether].src == device_mac: @@ -89,9 +94,12 @@ def get_outbound_connections(self, device_mac, capture_file): port_dst = packet[UDP].dport if self.is_external_ip(ip_dst): - outbound_conns.add((ip_dst, port_dst)) + # Add to list as a tuple + outbound_conns.append((ip_dst, port_dst)) - return outbound_conns + # Use dict.fromkeys to remove duplicates while preserving insertion order + unique_conns = list(dict.fromkeys(outbound_conns)) + return unique_conns def is_external_ip(self, ip): """Check if the IP is an external (non-private) IP address.""" diff --git a/testing/unit/report/report_test.py b/testing/unit/report/report_test.py index e5c8b61a5..4222c6d46 100644 --- a/testing/unit/report/report_test.py +++ b/testing/unit/report/report_test.py @@ -61,6 +61,7 @@ def create_report(self, results_file_path): # Load each module html report reports_md = [] + reports_md.append(self.get_module_html_report('tls')) reports_md.append(self.get_module_html_report('dns')) reports_md.append(self.get_module_html_report('services')) reports_md.append(self.get_module_html_report('ntp')) diff --git a/testing/unit/tls/captures/multi_page_monitor.pcap b/testing/unit/tls/captures/multi_page_monitor.pcap new file mode 100644 index 0000000000000000000000000000000000000000..d813e710bd87715700f841f3d8c4131a7ca720bf GIT binary patch literal 284634 zcmeFa2|ShC_dkA)d7h^-Bq~#;%$a4VOqt1?p^zbCky%m^O(are$XqG&T%wSv6jGTY z6v~hk|Gf{+A>GsM`~UoYulu>b@992W&*Pl;T6?YcTF>5lt>^Uo;k{%W1Ri4bwX}pl zAi;@Is<@H0HF;TW++;~lYJX>@5MLZ~1Rngrtt2nFiB9GQ#!;Upv^cp>}< zF@)5NbQCf8JcIx*LMI0oI}ZmBVlNMVJ8KV5eqmy3XKP2_7OMOLp2e%byMJwSsSC-@WwXxiw*rBLeAY!LqanY`261e}Q@-;rmY` z`peiale9$#7n*O4n)Kq(x|lz&TOjGmaEmPIZ9Z3?g^Y!HZp;1nJrBH%BEbsBF& zAQywcRq*I9@MQ+)NXVTvqk`{QfRY~5;UHRpf8c>cSb(c5b_VQ0 z)^5^KKrB(;Hi0gE2YyHQf$jq`PnRBn2!jat@W2%o5ycS|!`&q&iYqKGMd;wdZ*6Pq zj%V%eW{p6Q1p#2haRei!hL@+is|&x7sGXRk&><=OqpmjAM-e!}qBz1r%l}m~qu-8G zErL`+?m?;`#aI5XiiCgmAces-F{C26F7%gwB*A-BaUI;mt2zHih~h{|AV(CSC?O@l zA0cq2T%GbqSi&pXK~0sA$}1@109CpA^ID{8GKAoYkqE%gI0&NZ{cEo5M_sX9bHx^Q zrEtxaLU^SH2Xh7d46dyDcM!M$9w;WQ_!n@W^2{tUk9z4hOj_|dBgg;x{I`t!hxq*d z6GFr{5OwhQIi?Zgo19@xXVR{XX~e5?I`C!$U=0F6fIyHh2P?atr?sb-2chLrRP5qe zdfK?H#4Tbe2>EkJS98IufWupXSQzv~5E8*qy{mc`xUzf=56WG84znOQ2YDa$8LFT8 zxb}BHsC+6F!!cQJ-S2+N;gJ0gfF&pZE<84}AMxt%u^;g&cq?io|1#@*NF>F^6CV^$ zh=1Y<$o=5;2bMtmk|&6N6i=Wf{v$jAS@Pd!oloCM|1Zr(#;M8wd=3Tk#!oL8`?_@G z2wrd<9?NqY)a)2Zv^s;tSw08(XJr-#GZFk`HzPUX5cm{4mfwS!6Cw2dLH<-gzT64l z-8PND1+&p%&us{V&N$z4z5}27lNXd|CiZ`Nh6<(J*2Ro#okieELI1Tf0wIB{F@R%& zV*^?9|JS(8fJ6bl<-5>d+=)U_v&$d<_6)OXiT}+oU`{}_x`tX^xj^gmU|)sApm?%* zEl>V;6@vIXYovd`jC9q%|GNtL8*ABr$;uP@oa#F+f*i~f;qmh-1i7^7GK}eru5~dz zcKXH2Dw7!8L2>@ZDugNs-2JI9BZ@X@D(+EKR@Rjjm)tF8w_Dg|x6Ps5;&$L~x;@&; zDuyb$vb#hDghT~|#qEWJgs8!#JsOI7da^>2!cs!QLc(;aMwWW|iuwk6vckKyTn*f8 ztv&7Nw9pr|T=%(n+PS;fc~a=jU zN{S4whrq~isyA0}UUNnU*H>`VAeS2{bS4HrgT0|3gaY`$>gEO!_!&OBi}x}q;u$!F$C`Bk9;$*+9eo=PIK&d_0MQU)z`8k2bKT^@ zK`7gTasS@7V8FkB6VM%jz}XbOv<_J9mQR zI>mC40_ABIc7PCupz(sklYyh7t0zS`ffIOa7@c`^7HV|W>qfVaJIGW7H98b`ey=## z+yW_Yd5a6wX>bR=ML^L}&7_F^KrB2^PFPuJq6{lzF9k#s)GR@x!cSClAj=B9m_bHE zAa3G(oBY-U?tyst_wjIuNEGWF>fm)GE-nE?KHr5c90E_mL0w#g$Z%lyOkp_0Y6gn` z2}i+j{)Q-jl&Bx;MLpgoYWXLkR>C2+8>_2wP_C+kBZA@(VqjdrRe|FF0axktV2y!X zl<0%&MCWi1h+6)4#K4X|Y($i}21Z9PnFNiBBH}h=*#dsqp;aO>++Rn;#H!v|W5TB%=Dc{|s%6`2lPu-;D$`;i5@1-fodDl^_M9f36 zp&X6~ibIHjaRDOs$NdM0_!)@Cl8p0FqK(&y21HD1{qG=R+9Wn24t)coBT$lqMnw^E z2eRx+`L|Z+JD3q=&a5M13%tIX5x31_BchEqv|BzOM25DzBMgbS=2Z-qY4J#4vqC^|66Ag%{ zZ~fmv#6$!cmRqy3E*KrbzdcB~~LIRP1#evBK@&~ENy z5ElY8?>=))G-$6&n!;?V#NR=piz+UBeSdL_@>dRe!>c6(asdls!rm-Fi_Og);w> zIU@0XtVAqAv7rEt2#Q09fpGyM-mdx&5b+5Rjpf!{j1sNAPBb8*%zw!o(c%C$BHqdX zqaz5r0F88l=6B}{jmc=eX5V zBgoW)K13057qTq8_|v9UA{v91tu_0IpVtyGDg+x5B_2Y%br-F&BN-nOv4c|Y>7TG; zg^0fq^#~=ZaJ{IV{%_6xMAT|V48=;sDij;CF>Cp-5B5H+*Br#ZtSc76iCWZ|_7$BlL z-hY6I1wb?wBG#fr!@17NtN@4xM0}k6-$6u=SZqWrNe81NaJdM5h$5mmvTV9A$7q#^ ze84bkGUEJNB8q2XBchNKv|B&rDm&f^Kq3n4Ej{ul>{ub5V7>ge}IVhvak}d4n;(zb)o?gtGEAm5V8F(HX??< zhD1y@gFZwNQ4(1;*hhr3O2oHdR)`^@BfN~>&`v4FAg`%gf~TKUP>)3^AchHoB_S$A zN0wD{ENHRFfdb;dO`7R~qe2+u^X;Dw!vZ4MDkp^1js6mB6wk?p9qj- z5BF^XrYa70iX*cjr56!-h`AE3BP z8CHtdqeLsL6AdV?R`cIMaiwxHgc2YoJT_FZMeTP(iq{fAqoOFjT*V#$WRwr0!W};s z4k(R;6>LXbNJL0Lty&DVHz3M1a6v>XYBb_*WZ4Z>UC&Zt3WM} zG049Tnn{A=YlCLnCb!LdK(W&X291>z2Kmf`B^eMjjjKU3_7s~HBod&`lWAz3mrJNN z09_ecA@CyF3Iq@tT4BDO3=s{84v(L$fDE>mhKSY0XvDR4Wx^ddC_p0;LAx^GB9VJR z)G6cQ^2b-)`7B@1+cr}hVL{_GD6XaJSt5km+fmcW22fK#?1I1q>}D-V|npdT(3KtEh6 z03R+T1^p5TBo2ZERAfjHtO!N~8)6e^ZQ}$84B%h{2RT9rA%KUAk4u0{L`XzLL`+0N zL`sB5gil0(hr~w`04L$#;v#X7xHvdCcsTet1ULvj1ThgV9xnV162XtaK_Y>gJAhKG z2=;P))?GBs_!dR+roOi>%2|ABymy5hk99XK?(WNxeso^YJ*lt$kV-q2h7xXpa%CH& zQeG^EN}Ti0uK_BxtWpWti;YS{3()aOsBI`zKrI(R+W>khq*C)IwBt!3GSoG?9~+e< z5+UM*5t>SC$qA?w&x=MRgXCO8r6}h2J8^iJ(o!Q{J;c?18_mum6>4)t!%~YX#m(?~ zdLg@;*?dfA9FgT2dT(}*vmYml@FhP=sPFi2Hm=)qAWbXqUr#0d1`@}mh?3(Tn ziKWRV5gALJjgh>yHH7DTh%D@&dm4v-N2LjZ6Kk^)_nWI@ZJ^*df0Jg>+XOsT0wxLG zun)-P{gFyQrH)l9b&X-8lCmCj{J=-F{Q6r$bl1-K7 za*uRMGPR4>L1baZ2Vw{4o*h51xkp(ax~KmJ+C6I>4%{QhhIS7vbod(gFrF~!aKDyJ zLwM-(&A7z0{QJF^G@f-f-ixP^@hK_^ren{=-(=qHIxhdP_oPzA{Tqhf+pQP69!l|K z5E&%hxf|2)uXhhcjMlc3W_z}#+I{DlyV%U#A9-KeGWC;S?Jz&3CG{g}=$=|UaxBGv zCsY?o1|M_}IPhw9;nZ5U>|WcS%y(C&*1r*T05E|%gLl2CvMhoAKM}PuwNAq)$F_QG zgrY(q=~kxJU|e8oeXk8QzXkICPUjUERrN1gC>;pMv29~Cp+rls6Ah-;0{#CTQ)^8! zax7ga6m2k?HywdKM9l2HFCVVbE|%{!Z7QZjU=jjx>D+)#m`9D_${JO#@wTLS5-yv~K`ihgWqK z*iDXQiroTt6$y+mrNp(mf@~?Qf!381>bfRd#x@{@MdpKhk_>#24I#n1al>ogHW=>~ zO}cY}wX&etk3DiRCZE}Y^BCXE7h(JMo0PjNkb9Lsg*9fo=vYC=f0M>WrCYb5d%~`wskGd35CEM21yZRu z4&xr^c!+pL?RQlANZ_}Y_5x<2)tR7vTn}ejIkK3Umb-y;I-t_nDwVwVW24foOsH$< z{$J_}sC2p-tt%JQbq$qvI);kP9;33ngM1WVGm~AjuU2QPe9`=ep1CFl#|wCe*-x}r znNLh_qgIt{2zi|oN)RMzc2P8`uZn}mRQ}Bab(?=ZmD)3hzkBTe;Bf4woA}M=_j}67 zoflHl_td? zRQhQvLCEID*-}semc2>yJ=N?xib`i;R!XNiWDTe^u}Y=)CfIb9P=UHmE}(T?t}Dv| z^fIVx82CP)l?@d>hzxaQGRH%TOj zy0i3ab0DlaZa#oYpI52$$Q~P&0^UQ%XTrx8mM0L)mEp|*9UoHZ z;2yN&1t2oiwcHsSl_XRl;sh+>FC(rcC!o?xO*EnqB@|X1rOl9?KB%8%_LGTjrzL|lp8vCd zJ(Xw+m|ll}QvPztQcr$_{T`ut_qH$NedV}b!DMXLy%|KHd%nB=j!HjeB~jX#_Lrav z>jtxu$_GqV()hZd4yZJ{N+o90Ki3U$Vi_6PwC?R)s2!OhtDRb9^nVbirF1M2D$k0$AI`Og@j4?i zATrbyBL4MeY``!?yiJBiTpLJ$_Nb2P) zu1krTBuhM$>g&(9>1S7!r?eFlNqWC4++J{AcFty3w`_CNeus%+|1(?saE7`5^|bF1 zdP}S`&KW!tBwA>A<y6fKz)y2{eWB=Nqksgg1xKCWD!MQGP`jk&J)A4vXM0= zB9iXZUlX)Eavx=t9lD3x+9kV%==$Ydtd2%pn>zrN`m@kfl7+cr4VC;F?fI-L z_EUulC{XzO)1__Gj41hVAz`t?n$gK%ph}Lt!Ss4N-+|7ma;i^wC(~TLOz^f9Na*kW z@xH&W`?K?{vVT35dRh6uwJ#BE?UuNb?=6wCE3l$}PwZ>joJa9QC$`G<9Ea{P&H6(s z?H0i=aRBwfPDrKqYpAqMZj=(%2Un>Sn1_u@4XDikD<-t#m#dDQ0NoK%2_HixMTiV_ zwYh_hO5txHId7t#ut06!tR*MRN-St9DME6tp;C);k7KWo{GA$OWOB-U<{{G7qfLju zOw?{=xcl+mM8egDuYWz2n9Of& zs?yE344$G<5UNfs@W*M-GQ^RYAbyvVeI$U)1-d7*7~}8_dtjnC;K89`f`GHoHPGoR z9Tf6~UaUevRLJ3TbIa}l#nnteBh=Sc6qb@BZh&1jcx*ttfCC;r0f;+)iO7T;wk}7m0c#oUamN z*q1*ohP4&Cz{`IlxBzIJJ#+|g~ z(GG4})svjSpjsUOVv`Ia;y%F^n*pC8;@8PvA_B5sd$1nyPh#_THSk}?CIL|QuVXXd z3(5ehKdGCHG5}Eb@TK+YVq)`h6UML`V^iWfdSROlY7}5b0k?j5%{VyPY{1f|M)IjqfBSI1Hi$|(_?FUOiPuF8NlZNfp2ZmS= zr~k;Il-sJ|6r<86f@{%rGZi^jb)&YiLv(^K`E*`Y4Vxr>RMm*j_|XJJHROeS+yCh= zt%OqEbYl3tF;N5>qr!T4O`O0soYX7j-`QZIcxJiG70`?D8YBuTh?xEgTcQXwK_Q;` zB_fDChUoQ(f08JE*WvKXM3D*9{p&;#co3!T+x6-uB2fka>OPoUuP!E0@Vv$t_U9l( zhz|XLL8!C`9fYVxkMC?tLy1Tj){U4YwFWdUG%PQ6#6=V$?DSpUI>aCnq7ci_VXe7} z7}tlCNgs3bdf=&mxrlf^BULU~b{9$~Ec%k=~ zh)l?ZSI5^Q{)zK{*FW(~=O+Vo|JwP(1SkWDtXFqj5M=C2l}h zP4J^#g}F;)zzl4ih<240%;_64@IRq#>>r+i-|yto{;nrfX0G5mps?%l2fJ;PI8sXF zk#mOfZdFZQC{FL78^PApB|H2GW@AZ}@(8(jv;tT~JckBuR$ zYyiDDFoyObsu^fT_083BK^Sm>fEpU|)N59e?>4l7G5ouBL3P))AjbEBhWV=2>WL*4?LCsmh*E)F1Y|(1v(2?55V>`5uuJ6T8(Ub0Nka5t9N?@`CkBuCrXop_hF4~M zpc>x5^9>{CQ%pLCCfYen!7Z^ky=9q3bjuVE?b!2WtspIvocFS70Cad-VAgFAz(hCbEqn4;~dPN|=LgX|tV1v+du&df4Q z6%gYD&j;5`OkjW6*!acgCSYbZyRUcIJ)o=V1xUcC8iGD21(vfKnGTGvngM7eB0F3ho#4(25==@t*&{biv zXjh>c;$#|0jx-;DuIgDK6)>tT#D<0)#EzJaLcH<|L_-wfVYKtnh%Jg39XC3^v|9o3 zk)Yac&Ddd!U6xVlcRIKxdvRhJ5%d|o2YT*=I!Y;HbAD+L3X$-ah+vWPXy1CoKXLx= zx|e?Gd|9CGUpv3_HA-Fc_3G9Tq6`4ktsq&iF2?y~Y8b4aXyb#gHFl}Q9cRhexN=a)AW3aUm ze7OzFSrEc=VgAcr1pQqpfNeq$(bW)J2zP-}8$euJ7{eekA?MDptVjHl5dK})*e^ra z1E~AgA>0M(ctG8?g)yM+IVO|=fVxL1)~kyN;g2R5!)^>=2{jlVlk@2CKsC>?oQ2ph z;DRU6;o%I83k~}l#JwoQufIS9+n)gO!$!m=dyI}7oljK`CoWE5Ytk2NM#K*z(?g^EUx?|JwOfl_+&j z{-o|9lmURcN?@T1OHZo?z&Jn231ire&JP%YuF5n_3K8>ICkF8d3UP&|z)fhxi^s6#?^`(#F_ayxBW8kO2=jN^cQl>c;RItt{{AQQ zvj4;Lx1e|2fP%tt;*y3h`f9Qc0y#KelWaJ?EFO*bs(>8|i5+O`q>z*ftO`xx)6znTt{&u!s_9Ezn zI}f-a1)0VV5O07T7*CYN(2>-6X?w27f1l0ZO5MCli z8DQ-K1gP5~hB5$9SAV6mW7Pnd5UvWq7eFemZ0q6J%9Uk5g z8yfaEh{sWg4ZlE?Mj^IuMEnqf(Q$*TL?_1J*dz4UxC(aF4o(;5rosHZWb{E2ahczX7ih#(=J6j_h>C(i#}N8B%+&kWT4Yv)gVL>WM1y}Ab!Q3e3& z5{9l<7vucs2#jGjI=>_ny2>RE?J87bU~ZbE{{cnlDpmuut4=`ULc_*jN6bPYVwQ6l zL^TxR%BmK)35_Ut1*79e=l`M_3L7mc2K$J?0uedfx-uQ8X)KcmsESZWn>cKD1a=Ro zBLU_K0?ev|9NrNQ_oGLB60SNn+!6i>50L!B?+9OZ2quKm+<0eBfa7{kAp2_J@kf^p zyxdRSb)YctjAtJ>bY*8%zC*!RvQruM*`8i|hr32>6?aGO5`R^6?8Klbs(*^$Dz*^* zMNJ#S3lJ0ZXP3RW%8Ne<;oo&4{xXD#fx3Sk!oR3#Lv@`{GzRJx`>t0P6T-+uOn7Vz z;qbSR%*od15Joj*5+8urFyNkHp7->Jrhws5k%~dw7;vngV6r)=yC&Jdc2vh3s`{KT z;PA(mH3cnXuymyY5x?bO5I5@BzzcP>!feN(+EDd50ct(e5f`Il2tY+WUSwB^4bff! zBGw|%qeivUu%#|&vBHVxXm}Djgu_8Q%_!8dtqmKZL^4F2#C*#Dsyti?I<%O<8Uc6I zHv^4$4wQ#c%_4UuFo+xNI1HvNppw7#!Awxe9~bLRn=J))oDUpXMs#`apakq_1a-U* z5JC1q9UBmz4}&QSsN~13@eBr$2|54p(|SZm`2-vUA`TbV{n(>tedgTnW^^67@1(Pm zHXo7hOgqOUoX9j_bo7Kd?Qg#c0a9KY-HW;0a3j;ilq8~Rut%o-%N~(T^GkyV8Jb0= zy|MzeP57V9czs~nQ=~soNhsb^!&_~Uy|aNwT}wuq_8n((bgb<~e8OlrVmm%cEQPIr zQRtP7ezc$0E(buWHh+TlN(x+HY)IArgeO)0;i>x0(thq*naAfz6Q#GG+4fE6h5@(8 znAX_l9e!<+31_k*@U>68R$Y8rjH|A^`HFBXPm-CBlIz#ve0JRm8S2U!Jm|%9;*{7b zCl;u}LEjqQg35`v*7(I2%^(tH)%=#d$lW)=3?ktOM2rE5e;o-KmMBDpUm}81#M!Ou z5!XZlSqVXRhJR>UjkImNXhrjC14?f3G^V_G~e-#P(6WL^O^)_D` z8l9b=T<2!bwK0}DN!{@F)ysCAFMXWvUz~h>UjA^d4{7M*y3wqMnpwd`-%>p?&agiJ zAkCn*_X!-ajWouF8*^yOP8bO$sDEz&j=CDP4f&!O*zpt0Ps*9-NJxivGzW-249g{G zrC%+8LRs(SCV;jS#F`=4Lz-2bqn z?rG$p#emNN1zVq|mZiP|aKxqH$z*6hcx?2_tz77puuJItgxXw?lLvO3g>f02(|t*ie6v4&@cnpKLgb@(QqFapZchFoGP*7A^&PH_@keuANm+yZrjA z_OTnc&OfuSexiBfwy{%$r_JHbx)}{O`ws+ET;6?Q>9}w~Tl{PN7Ps#SvKNk#)4dF} z*Q5{lKD%j%^N9Bt?x|}td+IG6^&&&n6&AmRs6P3Ie@^I8uAu1i@lPjnuWQA6&dqG? zKFqpJ>y^eig(I&s7G7I9FR+b7@+xSk-aEoPKe~B@>0Lwz59#Jncc7w10 z5%$D!b5rV(9}&VYLIqC>me|^JyidN+7Z9frZHRQuV#yEN!tjtg>j;9xVOVVT41a5u zT)wWerAz2lf5Pcv<;LcHovq>WEfaiPb1e90X_WTtHe3idFMLDDmb5(}!L%XcS>u@w zTQ&sY_RS|V>NwBj1vnIYJX8J=RbiAl72c`(q2RTD_T!F(&!xN$LaE~~?LP;}vEVrS zPf*zyXp!?Syd4{RlU!xQ7vh)fq!}(zl$gPg{MxYfJ}*g-WF^t|To1`t@A~$zZm+3m zPF$L^mm0(kOK9rJP5TkETk4+IA*S5HNIEOZn;rQ)OC$I4b7k+Z zODy~6aq=l@k{;`R(7)&Vs`a66@?N}_t)UON4X*`JI6gbxV3;e%~a{_R#Q5YqX|34&oOjLFj~<0pzPj~obL;|sUdWtJe#O6NH|LrjZKNH`=cOgzirW-{{; zsDE146pu`kPGeA@cH2QOT+K`+*emf!`Ks#Cjy}_vC=#7Fnk2}&T=)Fxqgtn83p)0x z85SD(b>s$Trrs|zf0{2rG#|Lr_q*`cgyutW)|&`#8~yNbxax67u-(3fjWC2M@L;ZA z1yRpb77fj~h4N;*(a>@t#O)63M(+UUoX zs;p#c*ZYjsk+Vba@T&~*_w_rK4W7F*l5ZxdBFVJXsC)ZVd)_`p`{}Ts%)a_u0tF7u zw4RG`&v$H7=Q!VW&58X;ZB^-&2S%~&pT}Ni)0_5OZW||=`btTdM?}8$yuYBJ)V=8Y z(Un%TXqQcl;7)K$-IAIxZ=wXVo8@N`zF z@Vl@p+W*s@x55vM?#lnLeSw%2G<_vr@$nlXqii&Sg;=6oX;>OJ<(;t39;G%4rf3i6 z2ea?&UQ6uXGAPs&emz1_zxufH^&rTuhtK}N*$hf^hrNm>d^y7BN9!D@P6ne++n-qPI2`R z=8RC_>7dp;W%W>+;TwyTy&l`OqOlPX`+UR9Q5NLDi_9N(7b1)g6zNA=F!H}W|LxK7 z9Xhh)+hsZf_8J5ke%$XehtC{Fd)Xx~pWpQQZHsHO6|GiRqhpxHX9dXS@TL|B&!4un z=tw^h5%4fAW@iPX)0Y_k;QQ*nDY8ckmL}DQJ|EE$@gut*Ld#FHwKSiuf{^nHVSzDY zJ`L3kI>$Kw@D?BW!#l;tXy?-xqsdr{XAc&>pt92Mt4k?*yi5HYjg?1H!1zAWsH~xz zAE!GKy3AGH3ct~^JIi@S2cZtNNRCh1tjHYLsVjk@;5bEsFj zREpuMun>r)F79_PoAa3oJg<1Xjd|=*svP$Y-YgppyzGq0v6yR*LMZvqA8nv~7-$?D zb;q?cw9%ie$3!X1^BY<60IA^aPgC3W9opmP$l^Q}k4(DR*sNM?Py75ibyxOn9$Kn{ zQ__BJeRZz~@U5tfG#(zWESwD#cwDyk+9u`$8f26bgT&Fo?7>b6wX6+CEOr@)6jYXF zZckwv5{TAh@hNn=hL^GD5SLk{XAARJc3ag zK1ayUL*y<`(DSJMOiC)j9Ftsi=~Z^!+8c+?aDFT_G7-trQt7vBK9Hmur+$QIT=hs( z(|N6GV^`DTY^`;ww&VqQ$3A)Ai%+zg#-*%rsuBM@uZtu;7;t*~(6Kjmlyk*XW~cnB zzJHOHu6|r9cRyyP(`)WyWfh+}>B47xriLv{!Ws2D5OWt#QCNpNz0)N-XZOqcnRQ!+k|zrklpk2|xe&_|4i$flNWO+RGp1?=anXaBcKMbsk^l_6+Y5cLe$V zp7G~0NA*iN(yfbgz zO_W8i;uQIcPT{HT(2gp@+z7idRmbZw3Afy%%uiF>y&qxudTJ^_Hjd0o=s+{ z!AitDeDu{7b~A0&)K)*22R53chrX-%1oK3h=o=Iz?^Cxh^Kqn3{aYMSS#7QpsHC;;o4TF%>`RnC=wYytlk_rT(2(l+EqI zVP@G&Y$jLv2*T~156wS`zfPPyd}=A}n~HwAkZc!1&2o!i(BnN%tetyuTKp*`M-gPl z_XKduYb}1$A$>L?Nm1+8t6WT9ee=>CIP;bhUw$C$*AIoYpMa|eeat^{f~mbo!;R=M zLiFmP5Y}Ec>~8!MzUbi}zPrJ_`+>6OL4?XYSiCv#idlrIL3Um`jk@( z>=s-2`)*rM`S9IkePo)U7b(@dH7>Hyy*FTVsFs=odU1;)W)1lB`UxRg+KXzAI<#i} z1iHg&$c;*WM8JK%4!mVAx*N!dgLU*th`0?P_Jj2wJT@RcFMR_Mt7?9U2=@8rR(Jsr zB_QIOb#$HLjuc;m7apn;p>A1`erib`4+?`0G8eJP@nz$2g^K_7yRCk;j{Y9UN~GOx z;9J~XImn~_asE`0Q!7)~)4uwEV6&&E`EBX9i+#MRO5scvA6-1PZTPvp<7NASc;P`m znJWv^`Mkz(#8F_~ssu(0j}0Rh?E;T&gYJ~mYeo#aQ`pS*vo6BDh~VL68>Z9P;DQmy zK*S7y_}4br=8}ZvOb^4VJPs(IUUVXah?eR&4y(9F3t@qy^mN+ViyAU+D_uS0;t%qY= zGN%a46}9fZ>Y#MTWi?(h`e321V;!2fyE*17@ta+6#6{<^?HqKKqHMUfOA*?z5@ka$ z;;4h`M~vDz$S*X^+}_1|uYr^I!WLT7cAL^*FTbN|DMRzFP+}R7C>ZN5DxT~B#wY2R%% z4#SSnj@AYBW6I}bhns6<8JU|daTg)Z((inix~(qoa#sXdU`lL((+TzH;PEq`4rN(+ zUSvtdF_!DRbIDWU(wnnN-JSR1-9nqJr=MlNnRrWk_|V4(2F%%r;l0i}lyfy_QqA}M zP(AA{LHdeB{rc$wfhx!JXU{$!t-CnMVmM~Ny7;KjYc_+Ih4+p6Nt}SWgOOj(JYgc= znPGL@MZ~oIfWp4A#~r0?FLjBy4ziSuo*0w6Vf*@4<~0(ByOJIKx-HLXHg9*f3u*~k zMC>wE;G#d*E73}#`;u_)gOI4Koo|TKNTx$S)<0*Q;S&?zgm=6oa$b6WcqS>8b^D?U(u#Cu7pjGuQ7}f4IFc8fl*#u9Q64Fg(uZkZU0%a6;I-%`0BUV!KOaA&>1@7r#z-$uhlS z8~5`=pB@p+-WQAg#{(@ z$~^wL{z#ioGwDg6Tn2n#KTpLiG^T_qQv$uB1I?rbdm;Qk+{Jvt+{GV(D63_K4j`ute>U1?`s z)V?(T+iYE-gy~e*;x;8;7PGF!dCXvXf2&`5pKOPaO-5zZb3*}#m(N}bK2@8RJ~-Zg zs$7Oqoap!E)m30mo)+oE+duz3wBGT6<@u44}&q$3>61hbyH;W{m*`tiFD4%%6 zE9~&Ruat~SThTpjt2Q-L&97pCWx1SzbKEza%fnkXZ8NuTD`7aTJ1=7Ra_rKBok&I{ zAMo!pbU%A#RDG}9@6s*{y8?|@1o2g_POlP@|8DL%PnfCttkP?UUvO$^W0}3{> zN=i0|+b0h59h&9IRVO)#A2FP8DQ-&t_URGahC3{Gx3h8>AKyP*)es`7Zl!)X8xhS# z`F#KR8s^W&son_lk>`@f78N#mW!&`Jl5?1embXmHQH=kAOVDEI=gJXMkKw`AE*>`v zhT&kXZ~a!coW41-v)*TzB|Zzhn8S>;bks4&x)?wLKzt zPV|0vp*>Y1du5*X*o2gp>V-T9n`pVF_njuv9a0=pwCXin-ObUPD;xYyRQM4ZDyhAC z_<)xo$=;YQQ!AnH;Z}!__4Yd`B8TnHO}obl=d*os=V;k+OOKABf3rjc8TG7HyPkUl zzQl<_;VabMsZShonA7msEcjYOtqad~`<|bin`C38h?Me`C;#N*bH=6j&MxE)=jPY) znRDW|GQ*zRd3#zm=u9tF({x|+5x$^-cYvt;a3b$#8K&=-ZN6+Jzk0{JzwC+1)##cw z_IU2QBXqAQ(r!jj1jNmk8lFSC26|HHr471q-`{a<9_wRE$fWHJOFOe=<-cVp>JLgfbn~@_Cp_-D-ID66 z;~BzzH3TUaSlLLEH58VM_j>d(GehWw9HSoQho@yunWP)Av4_aV4#);}Y?`usymO-V z?N&j8eHL_#id=tS zdQ$TT0vVWV4u(D)I?`s0Z|M16&}OIBqs{JH*ccgK-gP`O@S>1%AFWtX;$ey}IoTs8 zn8JngC+a7PN^N7lHgt^-us)G2NRY{wYYF=4%V_S9e-dZLc9^pu@Inz(t_KwauqpR6*T+@Bd_f4Y|BTFMwZ=vO4@5R6nu2R8; zoL5#?i^j}1k?Dpk5bNaesnsidO12lv(eljJ*EFD!3!aYLmD&Dj`z0ouEer!sd_Rp3 zH<+C4)k$sYB79lUH1oiAySgazOz7vCr|uS4kWqQ;x+OfZU(NIhzxLkAk@WfSC6wS~ z6|YKRr%<_8!F9tH%2#_B@XK8k_g{PM#%@V>a9C+hAwYqNa^cXGT?huj@TaL(2eP&wie_o)c;xg5vB#59hz~B_`Kt2#ir_ zRoLli8hmy3?FVOhFEzjHWG(_38!F@%>sNlNK8-Qq{DWeT7;?~I#qxMF?4W%Tb<+fi3d5s4rF@+ z+RYlP2fknGc`3Rx0NE@bY)ffba{KZ^7mFYJHypY*jveQDMk>!2Mb=PvTx}6?)h5Da zIJj{6_?|Gunrnu>QA|Pfaro`8h`wIQeW`SjahpS&TC|<$&O!&H8@jrQz4~5f-x?_L zejO1^t_igB-Nh@p<*I$jsb-CrjGjhgf)^Y;yp+i)<7O6kJn19H1f01O4j!vjNSW>& zR@m%Jbw4sm{9wzBDvz;+n$k@Ee&zj2@%HDXPM)}tP-$2??|3tYj(M{7y|JCCwvX?@ z3t8XaP7zj}@U%4bFTWs+bL)VJXJ0#R+i|z>yWC<@r<61t_%GGGC}ftf=saZT8zVjC zI)4t2%HpLz(=o~g7Y~O6#`PK3lHFN;RN(R16xvjh_&7{G|2SvGQxR%sf7YTvoZpL| zhCIiob*}F6Hg1(nrV`S~nDO8%Lr<79pT6bin9e?(_9XKuyPWjGM?ML!m?paOt#w6# z?Ik-Y@}!~|zR?nqUd?4=G`SVqm~y<%zKeLV-c>pG;ITQ;N!Iz+ye!G6h#Nu@$!FDf z;m11Cso6+S+&h!37oYOP4Z-a{}7>g=l*Qb^=cCL z%U&9I@7a2oNtE*lPKa4XMk^?Lll6{FXTKu76s;wbGQTs8j_2)&*ekzVHta-C%EJqeLgdWly0=9u8U|-*%NzZk9uOMHwfgYg zB{gSKL%xD%$tz7oG(4;1jb?V_>Fz$}``VN$@kUk#BQG6Q^VZ#l+KyE?!TNc7fH4Zj%uaTPr-k6Bx@$k zP}@to#@a?19mtXTVd96*tmt^e_52f7W52EyT z^#@e+$asr|R3b_&!g9+*>KWdiy3e3>o$__))ko8Y8 z{^?J-7nE)W$GGi1&KJVm`{Y24W5RW%^BS9pxSBto%jmp`BYLEmc+ZHVr#C6Rm)qAH zW{!=;&wCqG8|Jq#o>}UIr1>=Dfhz!?@WV<&-=5kCq zq5}Kcm2$H7xmx(Nzd4LmWNQD_eV0z_JEV<$5H8x( zcU}R%Pd0lzn8-bwIf1QP0?#f#`*E4()Ya*p^3O&us4{4YZhxNsp>W0|(Z-0BYmd#> z#h}Ea{XO3(ga*7EDi4N+F&7Z72V1D=K>T{Hcu8w&bbe zr+&$=lugT1yXWTl{IiF$)4rG(!(Nl- zqenAjXu2BO}IqHuIwI#IB-rIc}xc za~-Z*hqF@4`V=qR=oK6kv=0&$=PWuRv-Lqem15+KP;t#YiPno}WD1{TkGTcCpE0jG zu^b*kydC2pKX z20ONha|<78=CdwPnBe-{3N1|;G1?#Ir#2+gwtJS{G5Bp-59x$8H*oI-l-p6kzAt;GBej_ zjW7BXs(Z6Tf8Kq@QoLACz$4Yw%I}Wou+z+*;}2A8`W)sia>vN6%aBzHxn#m_}u&?A;VcQLN79<5U8tYZ57{ja*6_m#WmJ{4L|O<@5Q=x%W^a zPtebgZvFC3i}>Ll!g^tQtB%o=VO?2DV{FM<$V^`-_lC#L?xenH(o3S9fJdL!OWD3)aNyhh zmZxcl=I~FZo-1g2ysx!Mt)$-JlkE;+W4)*>Y(8n1Y#30~6>V()b5D~fj_V8S2qP|J0_t`qb$ zKb5H=?q>9jyhMKm+uNp;CDOZokhiqanCCDX*^`JbHdadwhUMei&5}x=&Ybyvv0*ko z!8kSR(7~j=`f>jIc0C>;GtAE{vAa?y>Nu41UN%jfjLe&`MCm#8^#HBhB+4o78L^x9 zY+jVVyS?w^&C_)W3S=2OPRaE7X;$8wD?BoKN6y>;12^mW; znORKTm}K0p_wk@+gM?fn=cOa%y*j5%#=DjDXPrkrbr{yM;e7Bb-<{9Z(nsKbxuE&` zEg{v`y&+ zY}U48IEhm2#%}QnrR1T0`fn6Zq!E%nw)i1NpSo0!C$x>PnLyL$G=Aq3tz=c&>E{Bj z&j(&BJ#gpd-M+nyi;b^O;fqJp-Gl1SpVjCsox6bBbQN!m%5LF>d}T*lNDjsEaGh@@ zvrZ{i+k7KJ8EBh61sEl|I>gyI-BLczJFgVF#l^$;CC9MC+igqA)>dj2RKi8R2a{)v zo!CvqG#(jymW=wGyI+Ab@FLd{+tI=4i@j5p2w&ju~$$eH!$D)7}~oQ&iz5{10Fxy z8{yJbjoQ0cSwHtr*|lo#b1NP4pjxqNZ-m&5aaYl$r3~#xyVxAF3qQgQlF7pNQNQRr zGvIJ1_fv$ z)zfs7%=n4h#Dxw>5YgN%mCt>6Cr5CXRA6Y z=3uMEmSjUjXUv!HtbK3^)M7X7Mk79lk3wyz#r_k%Dg7T_i(T5wFUk-bF*% z|Hs@r1qQY)>%y^Zc5EjdqhqII+qP{x>DYG1b~-jX>Dac7Kk0MV+E{z9bN{#dFkio# zRb$kcHLJ!~&G z?gwJ?#NX8s5#BxX7|d+_KO$lP?&t*mE8;)Z5zATV=pd*Jab@cc9lqEb)d%8GX8FRL z@NLf&L~Dj+GyktsGX7H?G3J#ENB`t23Kvxrf*H;=7+dF^e6Cy(GHKjVbIde~GumYf z(8luNnQf6(1Ul&iuoMfAxQ_qYqCgQT)@leseC) zmuzWBAU?cRk>F2HSj8>3CHp``{P}m4Nrdj-tD^m{HY9=gy(;fE^tt_48~(0LzWoZ8 z8BLB~P_-MYIuaTT?SJXRO6exvA&rx>ndXg1mpxikLA$?q!7 z4ws(+gO&2DR6ugd^ud%FC(fliV_6MRnmc(59<4^X(>K6^Y6qF<2#M~vNp97j9~v7H z0R9c<;SJ`u4Uzv%GP>M^Gbrmin1F%aUNOJo?baO!(X@w()Hbo=zN*1)S{M;}fM{T``OCsn4eX2D zX=0uZ<_n}Iaq@#Rqj4}%@db^@i#zjO7x*;~4kn0_Y24hT=Twv+O3+1H!0kb^gtS+@78JE?a$1%JKgk{(%~JuhOD$ypM2q4X3CIqSHL~ z*az+ML;`&)5ZZw3Edl>aj%OenF6r}%=F!YP!+K@C7jKhnGneeWk__cRzB|Eplt4gPNxoW*^znK)Qc!trn8G%wq2nI#d z%-n-GRkC_(OC_+rhE*V!;1FAt;D58#QhwFXI zg-uyRLm()KV6iK6WaM)-p{d(pbO4-n zSPexB2=fo^M_H7Di*Z z`Cm&~*?ohyD1<~31sfi1fLXgbRt9YAwqLVpet`&>*{ufbGpYONLxz8AY~EDWF|vFa z!4jvGfIAWAH`-4!S9b3DYH?w|~R^fWIX_}Mc!;YiJ3CnN}h@2_ifV&vm`T}W1<4gG1H5yQt1)kamC zPcJ6_Q4STdmpH2O!E)+*h6o3Lm4q0n|6o_9AJ%BR9Cob~JS!L$C~*NYw&%*LDtP6~ z%4L+J)%DX!!{utVto0KQYG)dTTp>iV!BT}a%}?KPkT`4pOl%#BN=J%rz(O((yRxKc zN9pP~E`Dr~!>ih|hkh1vU`sJxaV5c?etBmmho9VqyZqmXNUjUTq^38*3R`oxf)`4} ze`VheYB1e;*a|=uixSacIgBt$Nb^Qza%mmHc3V5Uq40c>_o;2$G`^pA(wL;I!8EQJ z(NU5F&(|AaN1-&MXlnC)8Z#oHC!PQjR-~-qIZxB=~)I51}0S8LPs9gazUr6 zVuwJGa*Le0m%53`VT#n>ab&N9UiBsI1X-X?gfQJ)jD77}2!*=`(8EshVr5U_o7_FgKh=iz9Y^%-9o6 zS9axUi&{5)#}26ETaF`RGCEY88$Pd?s`8mbpB&$+quf)~M6$xuJ|z0P_5Rxw2rn*9j#C4V=HlHLEh+i&BWH?z5{iI-?T`y86y#=EnhH^I0E%8j19wA=HS*0+ ztGRsdC-|{UgNAxQsB?3Pb@*Mk?{pc@Kob_@)r5)Q>)IW1y*0huMZ5gNC1N1vu3*EL zqDP*m+c)hPiQGSvQrz9OgZhZ{Tn)Sy`U;!i6y#$h_3d!mM=1VWblw$}Ozu%-j^yv_A!AGv? z0`W*oU3S7;t=-}#cwVC9zc_{36nUspOhHs>*oe>8k?pMp@fCk?2Rcy7w80*YdIPlR zqOSNZK;02*y8NqE=kn4MN@6=)C~BEJ`4Sd4!TgE72&=L~8T^>e6od`;2`}Dv72C1+ zyuFjbW^})b6*jrw?v$GXz%n}NfoZKN9g=WDtRMO@>g)ayK~wT(#D0oJOz+FEiD$$n zogB*cKBt^1mxOB-plRlG$-aaey)tV|aEC`-Z|28`?NLQ86T z;D1Nc|J+UK{U2!c?vH5tkDCjBMAO`p`MlB~gRv4q+&3|{hi_9hK`**fl>str>X0mdvk-hVrk97*(kl}J%+_3zg*_|1HG#9t- za~J6%;mPh`l&~EZoE~Kq_vj;-M5rEhns^2xswLT3C27nPIDNazP(ELO|Z_HJK55Kmw~uxuxe-MP6dP18vdRId&Vj_~dwy61bKK zh-BN(=9&Ss@k-1I?mTl(5ZK^+hX0CrD_BFqnqKJFX94Qf{yBl zH7HOf5;{8piMv~rmGw;iw(>S+)2fDHkk{JoKj6a(B7(I;WMk{yIk(Dj9mc7>Ok2SR zVa@lHLIv0-Gzt5(Y+!TiA=)#}&Bc$o2(({o?ZKv!9MqhgL zFcz#lIT3K}mu3@B(ZNfMF?6ShZ+$9+W(+Fwe|=84=8Xwj5P=z`qKpl{?q59uC$HZG ziiPj+9NbPO0|XBg?jky*6!o55c|9t}Bxbi)AoWfi)ubL$3ZKEQU@x*o{%!~1jYJ~$ zdW{^ymRb8~OvlY%J2@B}uI*mo)+a>dK!N*9bYUZ_7{wF#F8EVMl)$$zXCtGZC<`Ww zxU@LUv?t_PHN!EZf~WF6;`s=WrW-vJmrt?Qv%6L2Y`LMimTmUmalE`_B}U-^J4GOG zTNo>>hCw=S?LQAoco)(`EgYA38{Xd{^=qAuzChcCw`aO(?!vSbhQ<&ed_ctTuwNU(C# z#Z+P1@gK!w^myD}?X(#OTgt6w&YU;tSWk>8({qKdJ9s4b$oy7EEld@E3XSeEzMG-X6nSAn7({Cbs z$>F3TL`>MO36Da1Yi%wV1fb*Jv2~X?M#&rF63`GumZ#$Hcu6>1;HU_97oUwu3z28) zaT!Nd<1dBMGd2_}D~#y-gq5g5R+^NV&N!O1Rmr%~p>B%Q4t0(2qdyhf3t2AZL;67o z3x@cPKGjdS9{V>`5tp9J16N1$L|FD&iyD1X->fI`Z02%x-^ok}9D(eDB-zN-@)Wi-%yn~W-ERp-- z7lvgp0AzU@HirSQ;!v7c1I5i4GW2}aWIlnw%b%^m!d-~k7&a(y#rQ2{>Ha}&(=s&oPpgrDhnX9 zzG&%}WlxEnojV*P!jmtgVSenXwrg2};JWOc^A9F@#0NTfPEvYR>ZaCaO9PY9FVS>204oPB5db0Ti~m3!w@`H37gS**S{{81;Y!jOz( zp=bH55rL%0@6mJo=7gX8M9e*A%qMEJ=70`|f03KA{4&1xlRAC(JilEzLM4e)$(zo= z9aazW9h(FM>$spw8oIzuQY)}ynI-)4blz5h&#tKB-i?I8es%e361-(p#2Yt6krNr4 zz39-%&pfcn2G$YC+*<5YXJ(r2Dbd!09DuW=@Gtvtv|m;LVk_etf2eYf3n?R-8Vp}t zX2z*(&f2>cAHOws@Jk9rnW@4{dBb8Q+cLNFgu;^B)eusQjzNRetcSmm9dlA+0!X-# zX7N@NCrp68CIr>m56pS0-AM|w{{SAg6cI=5gQd0(SJFwkwf~a)UUeU}?%A{u7T(2h zB)otrF~5BR+$d8Cmk#)gM}KIcnbfXjm+LW4nUaoPLovs)g>o;444S1Xe$({1auF zAdqoPWY}jkqZ;K*Z(xkNbIe$*cDhCjSvg~$c-{dlInDM?UsMA6SUK6>T}C-8AptEb5H^eALd1>&@>DiGz!Nw)x^TDe9s)NFFe}gZB$G!#`r+6DDfgJ`LWe#mwmc7F z8wVpQ2&`T$A8vM)A-`y7-v(si@XC?ldO055_?}2y?fe@sRC67WHzo}u-wz&N>hC`s zgUe|XJrSiwz4qV%a$7ANxf_iA8x0e{kn<$ecABgjle1xb+^lvPHkxnnh?EO$LeUh& zEHEVHsjVbB7kkTck!mPW3<GZ?UMoWzRFO-*{X0j(%0s<$vzt4^V$d;I9PYGADPtEx9 z_58fM9td)0Qm}4fzvS|ESPKq~Nvh#AKe!Lm_11)uVpfg3L(ZGd#ns30l$=xaBNnAi z{JVVo+380t8Y25onceqZp)w-Z4V9Q56+oPm|H&mU(M({z=i`58r>&FzE+2n(_JJ5& z^&b)6t5+;F|BCoe`FNZ|dT}gLzg)xQDnTD&43)lS5EcAc_BVdiH*wGzfdCmWst5Gw12G554WN)LdOhV#vxw_{LkDMNHP zRSC~WVH?+QJkVl)Bl@u6OX}a{f#Z&ttm9_V#|LOIu;1K8z%)RBxOW!e$Mf%XTj+qZiw}t&um37h7W@y1xQ~C4 zh{|BCz?>~sXXWc@5e=r0{_qG-tFq|Kwu97cS{cHQ!9MYP$`tNf^IXB9E-@i=#_sykg3oXDaqU+hCKwi5& z7(tLo57vPD)gEG_GL#9fM0~;EYlgx*4ZZ6n(nW6E|Pz>y;|IIV13(mFS#LST6eOqiIFUqw5|E&N>T|tflK~bmqAQ+?3P|DMLEyAN zf>u7!0KBvsoGF=;qs8?v;v#6rS6Z!H1eFGl<{xV(<>`NYsV<@kKE zxihFvkPJd8FA*SOOXw~8-xByD#o_yw2aupXP*&*fu%!)9J#%TaqQzE+?wYf+Aby^*_u*7U}~w zCQ4#6N=V_4hzFNF3h~6X0imTl7QZKcWly68XKkbEa4@k+E{pGxv`d~Bb+|Swy`$XD z;tFHXjwoAIr%~olxqlnx?n1K3f?@|o399p*Ih&fm=yfB3}5XOWC@CFLpi(mU^QtHs4HdI$R#BxfJh@gAtUV| zn!D7SLoO({a(4#rmZAB*ymF?{z+LSX<`g{w6ybgHE7_Q#Nu5(O>$EJ2g0p zqFUr5*bqFuB~}MhOVvE$B1CJ$=-QH@P7$NE8sf?bWnZf~Vyr&jqhoEecGU$^i>DT+ zS<`t(vmqkAz@6o~yvmKMi=l$sh35xff>X&lLs?53ON@N4+yk2f&dqL0aEu4I53A!} z*dtw$14|6DDz_?+f4QpXIqw;WhhE9-GV^nN$n;%O%$?ep1->OjKlmoPUzUejVv*uzU1&c&G=KGrx{a?qH$B9l zTRACEvYNK#>cns6bZ&_|O&HRz!@F-m*os^5e_L5+*pfNPMMHufrkgmHmc_k z7;%*TQo`p4gMLa5q_ow@b;;G9kvwe1PQblbagz04D5AbJTqLs z2kc(I#r6!4Z#dt@lO}x1{>DvtPqIiDG757h_e__VHLRkmpd3t^-;f85bHXvv+55yQ zKjV(G>Bpy0zPFUHDy+*KxX%~yKtINwruOjDHocDmf=^?n4IIxMnWtr>cx!ne((T#0 z@*d)m(=LcF8OeW4iqG0gwDCX0;$2P61xLfVh*1~B5I-ZXY*E*Nwy>)6USSt{@M*rB z#jaZ3H?ekB1W_50IQ>$n=9fOqN*yS~=b>%kFM+_~GkilzJ$E)*o!k{D&St~ST=?oZ z_emh5@eDckwwU39Ognt(Zl9hWNyaNjGIV`rh#AB#v#(|q`r`o5QAt*TO2dKyu!R=}8rO^+|;t9Mf(Q5m)iB0apyFnzH1keQ(|J5APYb>E=iqThrN`mC4&M-g=*Ty^MMFm zW49DnP;VKX9?tppxq!N>Ji4N$Ugpfil|!P7=c=#?)0wLqe^F1d28;#r$Cucz{sBUx zutoKOY~X2L)c06aX7^DkMDE&B4Bhx!wxlD(Gh+ETjQwonj1ivL3iQ%e3Na3?{ijs^ zUnbD_%)f)G&gj#2d%~pmCTyt!1j(xma-g=bIZbV5AJQVcL0d|WaIQYWIjCyJvvS0= zwR;OujO2o1Idk#x;m@Z+yDY6vhYN@_F>!ohVOtQ%ZmemrIVVC~Via}g30xKK)p+)R z_`bmqx8C^!S$RET=EAYrW(%Cx8-Uf!eUh@k{xC!f@1h)X(M1;d_%?mEkRQY}qat1X zOWe|dwi?(|5gOo1z_)iA=mdkKpj!ihW=?7nF{{L`L8RmrnZoq;@`^(F#1e^ z76Z{mYV`1xI6UzD@$qR3+3ie;)fd1(-M=QA>}_$;J1zn+`ZP^(&$n5~EcQEA(9eDi zUS~B#QHqlHzJIFO!FoNx(7Tn~$XyJzMgVXlvdwnJ zpF#sazmKY_4_pd7a0f~SdHbW6wA+6hA;4>*tjvIm5Dm%hDJ%8mSQE`-Bs+u$cZqSI6Ai>R_MzeXAj+3bp<_3<7hY2v z%33R#pO^Rj&vIM}3E2EM`5i5?zxca4xh7*l=r&u|CJ ztFKVI#dp(4(s1mg{i*XD`$#(GotJZB(vQ&)uxUreDCz{Ff~au-+*b4n;cxg2pX(RtDBYnN+O16n_nrV^y>Ip?$0MbfD(&|+`~7kt9CMY1 zTS(U6F1|j*OQlo5p(XIKYV?6Lw|1kxD)tBi?pVp2Tj99u2Ds-&uvuKy`a3;~R$M zR8Om$ca-+a{4pYx0ng}+J}T#nIsXgZUB0~(s*>t!EB`qnVdqyWlmz|HsyNyj)#zwp zM{X{k>5m^z6gTpqidz9uz>Pr?I{@KJksd64(lICA+&9D)GsX#(n?+ zK@HDgpf1pB$5JAh|1<%S#=eCpU90WOz!I4vPMedD6S55j0S9=U7QQ+mxeDe(bho%q z)hplXhUH--@T4lS9~v7p06eas9$(`;97B~b3+#lXrTKw-5mnD#Wn>4GA5{DcSAQ6J zK|VIC@DbE#6H+D%ISEC{)VFF=nMU)N9l%1@9s+0Nee+KoUgZgi4`Sa;rIZ-ed_XFN z2|TUY9LV@S6R*OcO#pNBE8CEliXFl0T*#V~C?2v`eQ`Y2X1Y+v5lSL^FKJlxD8+tC zeotOO=5?|vsQErxqBN`F;hXA+Qu?bw4c*kzj4RAZ-vGc?(l#x=mZH(EwW&%UGYrG# zk`zhy2m&xcb1|B|L2G)2+s3OAfBD2fIoND+nPtUk%ZXx83DWcv<3h%B z&jrXE>gL#2^S~`lQbUAbFwNgQi$&Y!E#^AHfWKz1t8Ml?F<5*783l9Am_KD8%4a#6 zA?8xnX@_I5VWhTV8menbm^ng9j%1IQ!A&9jD#*N2wAw0}r5TebzKRpC`q+H>Gkxx! zRD^5cj!KGJ<{U#N?FQx)oN{ll zZ$Tf^^NU3(xG%B2YiKKeZk{w3ZlxfOrPPH!vNxke2@yyBIjoa7Lpy|cP@zUl8^>5fu0?QH$@kpAUZMzJm#&`z zh%(h-D+CSCiNJ%S5_p@51Ag`5Pl3O53UR7d8hF6AyC}x<;e~nqb0f(Hct1tDJIAL> zfdIW2c1bBpYY0^*pWcvu9w+w=%~Bgs&c%_BvMJ*@)JAyWxwS*-ZCU=@z*5FgzXXz_ zGnXVdeosMt1(NJ-H}l6UQ&g%KeaNYZ6fkB19mEgAthmh7#}7%z`NFWS`LVCMy!J(7b# zaV~a;_ZuZuro|PlIhxl*1ZbM#iAVt8kEAMlX1h|CTifW4Ps#H<*@l>*p|%S9&(5w+U5vInTs)eprR_j);_M*12sl{a!eLh_s!JO|8Q|TOfmE@X9zY zAr91PjBrAG8mz&8rU&_ai&W)tu!yBK`taFja;>-Jm!l<)MA4;9X8IBwQheFj?ulC; zS;EHg9GNj?b2y{mr`~;1S%6IM3U)-@OB^Q9Z*wxYc~K2lU2}|MW?tr$qaz#iEtYKT z8mpZ_Tv7L|khX}HXWZk-gz+d*pH3^`k|nds2d?@TF{4|tFNb48u1vDa-4r@)P8;8d zt+(ogUGf5X`NGRaJN5xpIU1j@;u?HTsY14peX0qj&>Ig-$#xkW(S^pBLX#T9rhyGT z*}&HE-C){^#n@LKL7lS|!K4M<_BYy&f?j#np0o&UJOQap&@wx3IWji;*L#VWAJa1> zHYs)?I3f-)iqbLJtm{ zwe!StNyEe6ivMkoN2;0{Q~>I>GZMiYd!X~ZwVVc|&#$9W#oNQtIb7zmw=6Mg=lGM2 z>AORu);^iT@RPf7f8r&AQ-(=(>C8N72=lQ8-K{%b*2G^$SNi?X6l2P6i&z9);vls4 zU-eLO!ez7dUdLR7uVq5yu)YttNS!*1WSez-#EqcuapQky5}w`s&Yu7Cn9TQlyb<>w zabthbpP5~(k9_=ZCgCJt_-ldH19il;9!rFR(^22LMX5QRi#T)I17f2RXQfr_<4oyQ zmyvM53^c%X_Ec_}D+b@wzMpsQ9BzvIJZLWSb$oTQKW+Vmz@&*A^KkvttZdQF{bvP6 zw@irL&A;jr1Jy_+Dhg+no{x z)q-=hnyisULfW7m5C}`?$rK5cjxx_Iad+hlP?=tj*LkGgi*7VNh4YFPUFgXcVfhOh z@c^O}ir^)`iw%?2;vu9m+K3F(d z@3nycVd0n~e*8ClAZ}*)#Mr+gYAC-Wj=?qjiHQ7v`Hoe;5o7*}sQdPg*be#WuZXwVe{09;--ywF zMKt1mN2~xj|No6x^BXbhuZYI#?}#P9v;TsK^|99f%RAQoMvVLqhzY+D)BcKxdkFY9 zjH^NF4@9l(KN0^ihidGDaRp2DCnCwm9IC%CuBy5!^>|W$$&g&r zuhv+ixIBg~$l)83wG<&jMNLK~b{k=bb8W`K9 z19*EUYyUsaxaw~)L>6Qv952z%@+*UG!w?Mb{SifXPKXzkw>A|2|hsr714&Ku)EhiNWh^vuSS` zpWfi&2O^nz*_W=b9?W`j5l<)Agy(@|s!=zfld}=3(gu)T-Zr5vUpX9Upx1zqKQx|Z z_=gSudNK!Xet1HT)}Nm6n|lb=%S04}`0iVW!|i{10^5hyABg#kK!3yG^49!q!=8V& zVG!c)Re85zh55g(%I}(Sfr_eyFzw-2W6bj>(72r1%K}K3uY_phT0HR|5{up?{`Z=( zx7LTmlh}Wg$nb~6KWfH*tlGQ8_wKWEs8Bp6(rerij-T(fqd3{x|Xl*3P!)KKZ0!F+C16ei;x7zP2*jxkCVO}7C9kNAqp(`+>!2P z6I9c^V+j-lLxMUB6KtfR02|YO+wq+`Q(XvwA3Mwfdwbwg8GU<;@yNpE4G zo3F2NYo>=`q(<{38;5y#Rz{!ws_NS>=#8Kq<6y;xc-CQ+uL-0r1L!5LSAuoyb}fU_G%^4!_1Xi%Em>V(2DS1B97SvRJ75PdxP zNtYtXo(ke3W(YU30LY3FqiAide1Y5obC0kjVX_5c|@LJtW~usXerS+%w7F)T6d|=%Vqomt7QA zJzW*_mrA&;gRJ8SG9Dc+Mw1Q@S29=e#|&p+RF&({)cC&`KInQi-a+R>_>#m4^yrLn zRWSK(qoL%TH+C@f+J?qCe#^61`i@y@0`bYeR59=k@rN?YSkc!l+Sb*WCjYp&=pJEDW-k2idQLv1yUw#j$CZtLEb3j-^F9%<7G%yqw|o!8T`qXEz!Kc5-#A zTmeZ>wA@)*V}I~C)}tHSidp~wkR_d`F2xhDl)odH$mhNR9tV`XzQZ*9iSn~Z=mzZmAbRJgu^yO#SISuuQ@+=Y_y4C4BR>08K6?RvU zuBZ51To+1*?0c!m*)jyGGg0tZBLc_Gi=?kn^l(cJ=*1R(Iy&<~X}M?QdVyds;NG6A zZqy9vU!+4A*WVDdEgUb^Sbhqvo+I7NvJ37syxe$Hrj;6_JRQ)mGBQ^lsLxjfCv{j3|b_4M+>Tc%8ihOIZP#m+09+d;zN3Le*d{gVa zlbi=-s%YRGzv{oM2w@uygmc#r9^08mU0^zGWhgpEQ)``n?;ut_4;P6*i^SLwutMJd zcuc2W{FGMF2oR&%H#9e8T?7nd9MNZQUxlZp2AdfNwFbxQq4>bg=cw;K+4cDhSc!XU z5-6X6Tg%(Yb8nKG9v$``!d3{H^6^Z;S>TG6SZ#DpVk|jC35sPsdjwv{`%= zt_g#xh4cF6e0W)z1n%1=r^PG%G1FNOfQlHNxAX$gelMggppoz~TC*36cxaV5F2!+YX>b6hHyK*S1dxqx0zJSKj}Z3iuaAO;k{FutuCBljvUq5pZK z$ccc!+HOzCpV{Yq%G1^?+E2m<3~*@!L-h@AH-zJQ<(mdLm5TV}{B*I>MksN8Qf3mP znuW-5cCR-uo?ju~QMv=~4`3gA31YZ#tgQ6*w>aoWO<}he4saY@$7>K2r8bRHl+AWB zL@{CzcEZa{|zxziLWN&Y5k3yn@PQV8`amdx7}?yl4qqYyqVb+3~rv%#Uy zzN34g+P^Z_gV$V@GI@1%Nde8n?`pG?A~CBJ`cHxCePC+GrYn7e^Ga?A}TBfxuc+?(lYFj<@wr zvqEU34{3}6$|9ndEQ_rCI^8l!9kX6pLAU&UtTSBl!$SlV?KU)Tw};`JHuG~qgEmw(^Od{Mj(c8VX5?pC~%J=Ui~z@kzMHvZ8bAkM8qmy z6Wx>SLCXy&t?pM*6+0Y#Tn$IOXQRxXFWM%F)&}-HRF(`}Q@56fQ4u#(fhUm!Fni(B32og=t_y$~L{u zJqhCTIKGFj#o1jo@x-GzwhAXyDCcRlVdo0^b!S^vv(_J)h~7T!ilxW@h7#i{Ejm`=G)wy`SFNm zET(b4>2Dzfd8h7t$|`Er3}S(P926E^Ae@qt5T+$GRB{aLGtR0L6hW?*6O$^2b=HxI zbR#4IjQZ$@*Js9RFylTKK!;`+D3C^F&g`8GSrK-V^cSl4le(g>Sz%VrB+-(AkbVM+ z;4eHXArHCXV33%S-!)&p-h6-l>D+%Htr|S{hL`4J)o*CpNRiP4J7@+6M5fU^7 zbZp84%m-n&#}NdfF%Hg_byjIKNOv<^u5c`Y<=nNqQih#?*iX?>kT1RdV1rs2E@oMpI1J0!~1w?YYB?HoKa8Q3fylv?yCIi zJ;0uIyILN{mpDUr%J4)nf}nh9`0Oan--()>L`uOHxvvSUMT@1H5gZwYfDs+^i>+}Y zUxd|$fI_KW(eW`$)k|emUfiL-Q4v0$osA0~mv*#!0;|*ygIW@`>#((s0tuqMJX}^Ldce(;x(O8frL>;)T|c^{BK$i-F@KfzEVUHZs|_X+ry8YE1f8(LrrR*A zTLIc7-LBLTnl>K?dlqmC`73a3`dChaSsRN~cW^Yb|A<=v`tx!MahlM>cqh!9XCHn!~8cIn+T&SoJJ~OxX zHY8}=W{cVW^^{jh(Qh&%&=Yf(HF2ElDzYq$k#?A+yx{+1?=8TpTHgQBy*HcgP+Gcc z(w z*R0u}nR#c{=Y7}v&a7pp9?kBWli9Jkl`t-GpPYT^NR4ZuIELR<{6~%hm>q-c|BtNp`eXbu0}n7@w6<6%`l{94F)gxJ8~8EUZNB zNQnnc>BMhU87!q86dgfg+jggHubeBQAF}M5#k}gU zX-j>8G~)Jffhi!ZPy$>z=k<`glWR=-Ui}hUm$|fj86{U&)6E-R0@EB63UaFF0xqAR zI;ykDSYqsC{S1v#NW;Zg&+XYQ!-r3rnxEx&u%wfz=+eF#M!TVUlbN&Cap=IVa5o(2qN)K;EX#Y6L{LCK7|$fUv9J7PP-*#>C3WLFYz zzICEGxqOUI@T|sB@Gl62FgedQbm$6EZRq@N5+dW;??{g(yUS(3rE7s%gyHPur zVLfRiG0|Xg+2PplMuK6Vhr!{o@W!Jz-NZ_90}PGk5hC>u2T`r2bS3oOygF6b3}L6d zn*WNIlhGr{zXOQn_Qend9L#Ex9(OlSJb3GRsf20VMc(PkaKhky?dIf8sKk92%?WF< zgz+NiafLc@f5DR{{h1!xcYUqd18=%!d53j{&pjqy!W+4cDVR`U%JjrAfAqs8Sv%&c zMxC(fOVPO%FtUa$Ur`#P-5_PBCvHvC7}ks6hA&+x1?L%{B17D_(SvCP<{rj$6l1M zYz6~bJdYdb`-#@aY2=}Cmd;sMpE<9#?VqXQT#hfm=^dTFor^>)w731s9sX$Zs`t+?r%)F5IA3@I4mg04EEGt?+QdN7+GMXmR*hg5L109 zeLdPKPnd9J?Wi|NLft6vmIL# zf{7%_q2E{*scclxLGEs*VNp$^S`$a3^1_!8q~til-5-OEPJ|v6K zq;-d2C5Uh8g+{82L_M@7GV|EHMBt2C9F}52vNqj3-gd>Nl&S9H28OtMMkpUor02?M z*shcyk>>&KwR*&;GMo_3{ykD7E^wBC9uw>xgfxG8*YEC0p-@96pt-mWdYAsn|_X9#_0g>fvzmD<$^2wT+15qNu$*<1V6A{jwk_g`pn=^{<$D zSR2Un!J7u==o4*is`IdsAVT1cAgb$uk6?;FFU$JQvc8_ve905qr2#KwQFTMjdUI{S zFE<{fI(R(`ZE!UiNzbX}6L|74f3AeYen=X`^Qinf#P_xw5f zLs?-He3s28ae+wVmo;PWlFGdV-uEVOGCY7Sll%MurP#5GWt(5BB45fE(bX^l=gn&o z0{2uvjANhu9yxH9@vhG^RSb)vX4-kXmp`UqCto=Rp4pN$j-x0r)K4VNlJW4ZFpcj- zdAk=&jVn^2`0O)Sbf=doIMjl(lxi~Q!#f-0Qg1VQi3)eLcGrzp(vA`~+2$zh94=S& zuc(2B_Ck!49pX6UYbcSJUGyrPK>SnB>VWPdJz$bqyZDriJ&O|P}6t9uFL zO=Bi}*uFx0bN4Ky;nv(SHbY4;jRG<)-V4iusxEHi=fzBo2$LANAgTDtp#suJuMEeZ z?d4fJsRiFLP>cT6tB~k5Tx5*>YCk zxqmW=RF;P4sIQ8w+0)o${1IvEVaG0 zW?Fr>8}V9y_>w=vJ^U9jVUR=&jM(MI`M}pJ4CN*;9Hv~S_586v~ zKVT%LO>0ad-!yAp*rEV}Qumcdw?iTswi8<;ir_oD?;+I`R7)uwRhcAGRL zy^S9WY%e5Y7d^1CqIf1gbXm6yuM|V6I7<+G@S=t^H#x@U7 z(#=^WC`waX`*4U1w6!5F=kA_qWI9_8#|biwxoklO8;-D#b)K*N^PZ!@3~KOfk^uK@r6Vy6R+g80&rzE+EJ9G_ zw1{N(hJ%guWVW=J?y{CfEvUfTV#fE6k%^Uy$b`Y)L?(de=>d_6Z*7t2vJ?CsnfMpP zHy4QdewiJq zyg_#dQm4p+2=rL? z8~c8j;YB1bHHstwH}3M4YKmDcftRbIE}Iybbv3dYrjo|+8hwBo|8pddd><}j<?c(aA7N~3W`&1k1I+uurmnEKvu zzAe;sZ$a_sdE9HS*CABa1Ck1MIfpm7BrQK8q-%e+yjpn0nHg!>z;?D!V)9+A_MJ8k z7I)$>xpUpKyf#Ho|DYnh!t`_&0-3sH%wfOy6j8Nzs4L?xpJJ?({Io?dCaV{!6WkVF z)Kx_AVr79r!B=@fM|AcpCej+OQzN&yVohHXOxhMPSVmqkkaXdjHCwK`IkMQ}Bz{S$ z8pSv*$e{XFyYd{=Pc*X&jg(emmj6yx$(O>uQ^OsC*LHRCS7x|BRm5upEnciW`YFgY}*C2>=YxmT|LG+S%buVcxzD>rYzKa=7 zdDJ}+mfP{AM|M??5m9@~)Su;84h_?nao(dM=pv?NyjTTe8LKVqYd14irlJe%vAokO z^UGv7d%;AUB6xR*snb5>Sp3pz7L&@;+s7QUNEJTx)q6Fot_V$;uWPXGaRu-?d{nRM zv5wT(3u+O}BPICczz+JLu8;-8vlH(#RZT(7s9sG-4Pn^G>uQ(U6;pvewFbh%rSxd0_)eCxt_)Ca+b}-8V(($ zR?MJt3wGCnPkSn#+@IE$Njm&ciJp!{mH%oG#iBPRdPGuf4|mS_IDj0zm@_`FKdab{ zzLe%rV1#5fUS1*KNjJ3q;W~%rHGVg~NA4%hpbY$Iayp_b$D-a!`PTxsj@l zF-vwEuSMa4#T7crb(on)^+oR72?h!c+8E&cXZ#@dTRxKZHOR-0a zsa^bxV8&>)lC8&YE+ahbR`y{BbkCym^Ioh2m;^;%z^>ih4AqjSEbQ}(n+3{(o}mlu z33LNSaVk2<0{8-~r&X{=XS{C3u3696_-;Gq>l78&@vQ2d?6G1*me!j;R^r}>yB)XE zL-i7&e)Y|J?La(L+r945Vtxg(2Sj^_o*&bMm%Z*pk=9`f$~>KC&3w5x7-XMDoGNR8 zelWW}Ng^4c`ckkgM_9$^jrvHCb-k4*&%-CG_{8_WKt%ksZZSqnH6>05FbWqOWN2H6 z$}rhurcgd!O3tG_tTl);2@E*p0Ttd`8f@CS_XztF??Ok(=XT6dD=lAaDk!U0T_8-X zMuBNa-mAj^95?DDdZgX9XABNG-!x2I(wI-?HSg1JGzwXF9(!m$Y^z@VPOa9N?uv-K zq*C(r*W+3(IO5z$U3Rj=_UA1a7q)`FPqd(#+zQowT@7 zmAuA_EC~AooFB60jq5xRrhT0LzBKo@-fe;1E*J!e-yRSxI@9s z{&|ocbSN0cSg(Jr$F2qOkh6$8r!B}dw|x7|eUT{^G0gI|F?N>BM~#*P!c|NZ_L|}w z5^qVK=!@lSmftk6z)5B9S}H7|vg+S=HS2FAPCqjOk??j?-Djk z``6q?FiSqI4CO!)?TroEhisI+hS(^18L+vDsI) zMByJS=GP4f^qrA&7DFG^p!x|slg=AjRHb}CkX=8fzd|JZ<=$?N_+}$>GF?4K$?=o! zofeVa(`Fd*9JI1sh5B4zo=%qT1(>-HS{OE{@8lgmebUAypgrKE*d*w|7U7731>rIr%TkdDzsBGIa1l(~#8uAkQ*?u~Kq zTjGGYwcAW8MBi5N=Zw~OgP!+|+YnA`5H(?&t9+g3ufhd8CEgr^64EwpPM%iYtJ6x7 zb5-IY)u8uM%m8B_w_nd_?9RuhbHmpznKKNK)2}aU|;CiBuoD~F(t=T1$x4bd-ymA zPV^&a`Cu6&lIz^puo-we*)ZG<_*tJBC@M}R->S--xkD}KT%TS8b1E;QK6`31O>TN5 zM@qe$I3g$oATM1bHHe^TR*JL;iL&cv!c%0?j~lI9w^$de zsNVW}v`Te12C&jb(F*$$9zOj8u~6u!lbmCk^^uWH zaCOmAz}1-q0<*^4liKZwj|iwT6CuL%mnV;SeN#EpG@Yjjk9%@(+w0Ap*X`dsaJ=vg z*A(jH>~assOa4+SdSy42xsgn}<0KY)%r0Vtg|uW8A*W{e8fy@t!PNPaa?5z{2DAPk zq~fR9N9l{AkO$mUX*=%_V*6NMI#zEW1pC_PJ>!cBtLK-D!B(B^ye`?#h;`57C{PbQ zkYCbB&Mw$@ljg$_5+|2E*HatXk}fgfpwv5^5FaDFPqDt|u$;ymf&{P-vbIUi&0PaS z{N%UHx{tz&5CEs!dB&zz$PJmu<*g7Wt09}hnhBK`OFUb_ZrGVc;7#X$=!Ot|P$hiQ#f|2= z-ecEIJ3&+*#WDrw&<4xb_C8c4T zi=|ce-hezA9rEe(`*kA7hs>dsOiGs5^mfBzVylL+?FoT-g8?EGV7v{wCl~T zjH_8LG|s$_N0elrIaRB?wiDWW6g zZN(Ykr%hOer+&!GXwIa>{RZ`{XGft@swN=);4GD@R10@V!FCReP^g=d?KpAIVNvPlbpmy{gIe~3z4KRw5<1a{ zd(biBLT&Z%G8KWxzV|(c1-Wn(UglTL6FlgUj>$cXq+F$5mE~qr_1Kl(BxWS96Q;CU zE%Cy1G4(B?Bh0>@d`l)nX3@yzi3PqlE>an`a!G3!w3lt?p7eeQsX2rCseC&cKqC9@yz+LaFfP) zrJJ5Uw-8`mr{I>f&jk@p9;=EL>q(#%b~4em-d*X5upfS(5}UbhO~1nOzG)iG|DGM% z(tETuy%Ar#%Sp*|Y_=G2^k}$av8Ihp8$=TKn%dA~25t$-?zunKvVF+vO-+A$rYCdKooSyZqk^UH3?GF(NZQyX-~l5|g%`6MYP}r}4n}PK=!B?P16H&m8ui(# z>|V=0blBPX-1vqte%Q5*m|J}8N($Fhni~qKQyTWfcwz*~vwF@1Ci9y2m##|#JApQC z7QUQ7jvEw(KAVQi>uy(a=<*2h3>|}itMEmZ!7u1QUXyHgy6jjS5b=EYTL<$S-M_x+k|nKX$x+5=d-E zgo9%@*;Y)21Pg+YvP@i!=k#2`Z%?L)ziBJ$6%{q4HCnm&7@M`m08P~k{g(D9=9OMB z{v+>aO{vJSoI+M-80c>G>61w#*G4cp6i}hT_f$zwWe+X!A1?-xAD7?Sy~gv@ftZg6 zx$C|SimYFr&meAt41$OqV+-b*9Yt(Iuj$>(O4AyFa_Xgn`)Cb;mn@Tf#quo+8!%0! z5C^-SAD2FrVpp$7<*yB07U7c%agwLQ5+8U;=wWM7=n~0bLLbcteqpWV8U5 z{GOwaemW|SXNzeg-s=8m^(|lN-aBF1xmu;14pSU+SVUp%vy(Xc45>Xkn^~(n97ntT z$2UdMZbgv}J!i=xr6b8r;k$>z^7^gimVg%WM}fAf^8kGxR1`L!+*(Zx^Ry|dw;vhL z!$7H~&)uG92J|S*WF8h}BPa88mKQvf^9cC$9D}|LXKy#?@qwO@+1t;cF;&tj>N3QSXx|Xc*Kh#~ga}O2 z(mLzA;A<+V_(eXsN{DKm%p#sbHI&eE#zRu#C!cL1@4eAZqPAs1pvUg_(J^H<-755m zEz;&@S(Dvx=)irER~gibezTQXtOw7_k%jNX%pg5Z;|M~1@64dR@4DfE+MnXL|4O5U ztsRNGGjc}1cM0S@Q79b8r^b`l9-`t;>)aL}vY53G#@6)(Zf$S0x^JMntPBR8-&!+$ z0V`1^@jrE9+HrAYX^AS1x{e*4S;}>|>&RIqSWL8_Qj-wN)%av0zs8MPQb?_|@7g7f zNh!)fS0A1hnK$PX4A~{+L(AUGpL#yxOD+Z-CGKQv8>e)e#vEOfSD}1>MRgFsEu5_^ zNo3_{udF!Z+Z@@Pw>C0sF6E0AC!U8)kC4Lp=;bxEUc8<{oF`F>lzqzk7|u6Sm$SEp zZ|U9(n5VovQacp38xgv|DnD5sI<$aupQ9p{QBjQiQ_GEIqZjwpirV`3ncVx=Z7LnR zC+7ya@6{o&UfLzHwVNF6Fl4hFsE}vg9>$>fvQ+7seeU%cv}Datj1X)lhE}XhzO>zkC69T*nn~)&HFeWa+^#X3ymn`(s z6^MvB1y(yfwk>)l{lh$d>z_L7_kpE+L3yPgylL_Et;r~ZVNvpkG9O=F5?&2%A;-(_ zf$&z%QBOTYCizko?Q7s(jp;g1BgdqoNG0PT^Q_1)slUBa^x48Pi%vL$gApp_gLm#H z8|_NdcNuwnXwn3ai4#0d@fS?`=@JG_HxRW===teq?LkXZGDESp!hR`R3-!(hb(YVZ zV&3n+v1*8S!A7*^Ls8P4CBOaZ5qpX)pR8c(QSzqZp+6u~<(7aX_H|M`=-Ts+Km zadhRVSodnZCrZP<*Xd%hfU-M1_g=~41jNhtHW$x)4NZ^ZZ=>?vkdeEN5ECeEa(nFh zWzosobFVa+gq?h&GUY^~T~WyHug5K7*q-P3XNDX2G&^{6%@GpUy_}dOxjITfwH-M+ ztetiiMSas9WzgXUej!&w!*BWA^(h@odg0NjB(UhOdEdM&bp|8`Bb(+ybadADp*IhxZ6 zipCW!ZiE*naxsB1s9ocqg1AF^iRz~)DP=Di-afrwp$4v8_#7@?OfOB?w{WSMOvTBS z#H(4RDL=6Sy9M7&s_Q-Clj$$y8j`zo%PoVdIy1MeRrKjlvRi7on_dcgkLz?+361Ou zC|X*{xKsO?@?_h}Z-&$@jy~FaWl`+Vjg_K%s5PfN&qOlSqDvLxah#p@irDO9N_c^B zmE!EXFx;C~(!E%x(c3tAqg6UhgVEMO5#ypCZ5QaxA#$#TcpEoR#alMn#=FxWH9t>? zQ5)VHgH*lhXBGDzVWT=(#Wc8h(_$bX@BbXhBR_`A`zGeE@*Z0HE^p>Er833&b@#tfq?dUT9`5=l#cf38q5YJd%k|seMf564hVp6o{zA$&Blg z!N)!uXbXJjCp`VR$Eb%59^Em<{}J7}*lnkk#*J9-07Q4T&Ru^*cTC~;4RA!7seeRd zzd*$M8^pK^M71A?X8$E3#|0wppNOrz0OI^{^`D5e|J+8{1tQL$h+T64;=ul2do_Qw z@m~-*FA%Z+MC^md-J0Hi+d&OnKR*!ZXZ}%+To;H~e
01(T!bpGu1zaVm7AY%TB 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𝔐KWjnwTmBT8ELi5&SCSlM-G2iH0t63GN0fZIis)S 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

2J7d0Wc6byu%OgMoVm>;)`emB?#(qa#jST~ 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 literal 0 HcmV?d00001 diff --git a/testing/unit/tls/captures/multi_page_startup.pcap b/testing/unit/tls/captures/multi_page_startup.pcap new file mode 100644 index 0000000000000000000000000000000000000000..e6089ee2ba16fb803fe9e65254590bc29a9b4a8c GIT binary patch literal 11129 zcmds-3v3is6o&7e-R-v9vMnJ2#HNCxK%up;Ezk#0Xu+yQ%Cku2QA$A|lt*bQph#-% z5-ll&1Qq0!U<3jtf+oD$pnyCR5J>8&%HCVXAbPxC=fGYn%2?NcI223!*EqO`p^ zA@+F5@$fK0!%3K#Q2G0ori3cIazbo2n@jHUDfmo)oEH>OBTrb)LGQZkG@Ig(p7xbt zcBrCv_v}!eHZVI4=#Zi~idM&e8flbs>m#jN4Xj?^tXdPn>b2J4MpjLav}!W2TF+TE zy$DuUt(V7}Zp@h}#aNDEv(B7eQd~N{ zG@`6Dp}4SgenQWP!dZn2XO|R~mzs)Z&%%b(2UH&kbykb&v$TG`Kd4w4Rddo64|(+I z;vv^QDIT&H;2lkZc;wfcjTFSjn!DQdW6iC;qSdN5!bk;xaOY+$rpsKn5vzYwl!n9G?-)v%m16J*LHdk067FJ)gx z8RhIT=8v8bp^_gABgB;8o-@4?_?&$KSNvEx!z&`0x*1KG!J!Vdx|>A$dY$`e6&Z9o zlaO(8{P2=8FTpWRQgL|hVN7}5KxIC{?`(~L^xG9SsUvolHB2t$PNkcaD%jbjVc}A) z*aW}msvsAS0qxPan}#bdS0L%5jXFQu$~8$Lar51b39(`m%&Lzjh0g?%(J1)GjShB@ z9-fvKeMn&HIhW1Xfc_$xT zrZzjhU$7|e<;Gs%_r*Fne@YJHYOGTIXR8Zu6lm`xjnzCwiLTX7vzI@8dQ=orUdS*R zRV<6HVp*V0DODL~8SJ^MvxScW=-#g=Kzk=Cs^zaQJU@BTH*nrg9qam+#O*N`t3$@}Mrbc#XQo7O(3^;yStguH0$;tN+g!)yBsycMwb$?K>PDa%3%fXIaU!eT4#meiTcvz8sMtyju(E8I1LYayy5dHbMI; zvN=C9fYlMwJLHCkz{d}+dsJaJNgDN9X#}7`bjS-TUP4{fq5@E18lW;7f*rebpp-4u zRHGoMFaszvpV!pyAW-@NCH`2jDgA-+V~U_^S~sF_FmkhmQkMn&h;ovgi`Z0up4D%p zj1wX~Jb_qw7=^ZX2ou`2zp%1e=8TB+r`$nh^#OH6LJiiUUa7mY&mR<2)&bzv-j%_Q zT_#W#-U&8kAW(J`>(*W&yYEE$mvecogP59qt%8)-4(fai**)hVpl|KclJv^5U`IF$ zd~}wFf)dltV>LM{4e@O45D%c5phI3z$0Ssi78O7>$pO@c3{PIIXoslU`wVq14Qu3@ z2g}p_DO^w^eL%IBP>ovDsdqB>_=AEPnG0SWn`2VnYv|^eAg|bl0{zG^k1>5pa`c|o z(EwuV1FD0Bx~oM65K}~Tf8cuWB;PqI&-49!?}WCT4L-D-79;f%ItwW_8^n)7ATpX1cpY%6D6IK89?@KzjVzmYOm0fSx`f*byEMl)IBd zK}pJTJ&V&-AzZpP!zy4a?)N@+YqFXn|`h$XbVkDs2!AmXnOe{DV8U>W02@zx>TpjM3H}>!*ln(EDmq6_D zwxT5PSCUP#XukuODGejbOKzU+)QG=mH@WI)&;6gj6;+HZN};q*E4siG78M=a$gT;Ojv-+;9{<8hZZT2Oa@HdU59_G*dVk97A)k?UL55=R#|I z$!I58B%3Dhs}po7#^10Fwtq5HEcC`V<0c2bB8#JDl)DMf&@kzZc`Sb7AF|vxjPigq z!zc@GQ5L{Vv>fGHqbNti?@|Vzb`sKp2R5kLaEwQs7Y3|ucgbaaADO#ZHu1=T6?-}Htgy7?+x}b!2IMM zJmm4SYVEF7tCo^!j05aXaMiK|T(vODiysI+{T<6SZZM**Z|n$dowpeN{m6%0|7qOQ Q%iNX^%@~ literal 0 HcmV?d00001 diff --git a/testing/unit/tls/captures/multi_page_tls.pcap b/testing/unit/tls/captures/multi_page_tls.pcap new file mode 100644 index 0000000000000000000000000000000000000000..fc76ebe99579a935f81c128d90f418088cb567be GIT binary patch literal 235069 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 literal 0 HcmV?d00001 diff --git a/testing/unit/tls/reports/tls_report_local.html b/testing/unit/tls/reports/tls_report_local.html index beef934d3..688429e92 100644 --- a/testing/unit/tls/reports/tls_report_local.html +++ b/testing/unit/tls/reports/tls_report_local.html @@ -1,6 +1,5 @@

TLS Module

- @@ -14,11 +13,270 @@

TLS Module

- - - + + + - + + + +
2027-09-21 19:57:57901RSA2119-02-05 00:00:00619EC 443BuildingsIoT RSA Signing CAAthenaProcessor685E1CCB6ECB
+ +
+
+
Certificate Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version3 (0x2)
Signature Alg.ecdsa-with-SHA256
Validity from2019-03-01 00:00:00
Valid to2119-02-05 00:00:00
+ +
+
+
Subject Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
CUS
STPennsylvania
LCoopersburg
OLutron Electronics Co.\, Inc.
CNIPLServer4E580B9
+
+
+ + +
Certificate Extensions
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
keyUsagedigital_signature=True, key_cert_sign=False, key_encipherment=True, crl_sign=False
extendedKeyUsageserverAuth, Unknown OID
authorityKeyIdentifierkey_identifier=dff100033b0ab36497bbcd2f3e0515ea7b2f7ea0, authority_cert_issuer=None, authority_cert_serial_number=None
subjectAltNameIPLServer4E580B9
+ + + + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2049-12-31 23:59:59779EC47188None
+ +
+
+
Certificate Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version3 (0x2)
Signature Alg.sha256WithRSAEncryption
Validity from2023-03-29 18:37:51
Valid to2049-12-31 23:59:59
+ +
+
+
Subject Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
CUS
STPennsylvania
LCoopersburg
OLutron Electronics Co.\, Inc.
CNathena04E580B9
+
+
+ + +
Certificate Extensions
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
authorityKeyIdentifierkey_identifier=accca4f9bd2a47dae81a8f4c87ed2c8edcfd07bf, authority_cert_issuer=None, authority_cert_serial_number=None
subjectKeyIdentifierdigest=37d90a274635e963081520f98411bda240d30252
basicConstraintsca=False, path_length=None
keyUsagedigital_signature=True, key_cert_sign=False, key_encipherment=False, crl_sign=False
+ + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2049-12-31 23:59:59779EC35288None
@@ -37,7 +295,7 @@
Certificate Information
Version - 1 (0x0) + 3 (0x2) Signature Alg. @@ -45,11 +303,11 @@
Certificate Information
Validity from - 2022-09-21 19:57:57 + 2023-03-29 18:37:51 Valid to - 2027-09-21 19:57:57 + 2049-12-31 23:59:59 @@ -73,27 +331,152 @@
Subject Information
ST - California + Pennsylvania L - Concord + Coopersburg O - BuildingsIoT + Lutron Electronics Co.\, Inc. + + + + CN + athena04E580B9 + + + + +
+ + + +
Certificate Extensions
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
authorityKeyIdentifierkey_identifier=accca4f9bd2a47dae81a8f4c87ed2c8edcfd07bf, authority_cert_issuer=None, authority_cert_serial_number=None
subjectKeyIdentifierdigest=37d90a274635e963081520f98411bda240d30252
basicConstraintsca=False, path_length=None
keyUsagedigital_signature=True, key_cert_sign=False, key_encipherment=False, crl_sign=False
+ + + + + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2119-02-05 00:00:00619EC443AthenaProcessor685E1CCB6ECB
+ +
+
+
Certificate Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version3 (0x2)
Signature Alg.ecdsa-with-SHA256
Validity from2019-03-01 00:00:00
Valid to2119-02-05 00:00:00
+ +
+
+
Subject Information
+ + + + + + + + + + + + + + + + + + + + + + - - + + - + @@ -101,3 +484,54 @@
Subject Information
+ +
Certificate Extensions
+
PropertyValue
CUS
STPennsylvania
LCoopersburg
OUSoftwareOLutron Electronics Co.\, Inc.
CNEasyIO_FS-32IPLServer4E580B9
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
keyUsagedigital_signature=True, key_cert_sign=False, key_encipherment=True, crl_sign=False
extendedKeyUsageserverAuth, Unknown OID
authorityKeyIdentifierkey_identifier=dff100033b0ab36497bbcd2f3e0515ea7b2f7ea0, authority_cert_issuer=None, authority_cert_serial_number=None
subjectAltNameIPLServer4E580B9
+

Outbound Connections

+ + + + + + + + + + + + + + + + +
Destination IPPort
224.0.0.2515353
34.226.101.2528883
209.244.0.3Unknown
52.94.225.110443
3.227.203.88443
3.227.250.136443
3.227.250.208443
+ \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_local_single.html b/testing/unit/tls/reports/tls_report_local_single.html new file mode 100644 index 000000000..beef934d3 --- /dev/null +++ b/testing/unit/tls/reports/tls_report_local_single.html @@ -0,0 +1,103 @@ +

TLS Module

+ + + + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2027-09-21 19:57:57901RSA443BuildingsIoT RSA Signing CA
+ +
+
+
Certificate Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version1 (0x0)
Signature Alg.sha256WithRSAEncryption
Validity from2022-09-21 19:57:57
Valid to2027-09-21 19:57:57
+ +
+
+
Subject Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
CUS
STCalifornia
LConcord
OBuildingsIoT
OUSoftware
CNEasyIO_FS-32
+
+
+ diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index 8b01bd75a..d51ac167e 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -40,9 +40,10 @@ ROOT_CERTS_DIR = os.path.join(TEST_FILES_DIR, 'root_certs') LOCAL_REPORT = os.path.join(REPORTS_DIR, 'tls_report_local.html') +LOCAL_REPORT_SINGLE = os.path.join(REPORTS_DIR, 'tls_report_single.html') LOCAL_REPORT_EXT = os.path.join(REPORTS_DIR, 'tls_report_ext_local.html') LOCAL_REPORT_NO_CERT = os.path.join(REPORTS_DIR, - 'tls_report_no_cert_local.html') + 'tls_report_no_cert_local.html') CONF_FILE = 'modules/test/' + MODULE + '/conf/module_config.json' INTERNET_IFACE = 'eth0' @@ -343,6 +344,28 @@ def outbound_connections_report_test(self): gen_html = tls.generate_outbound_connection_table(ip_dst) print(gen_html) + def tls_module_report_multi_page_test(self): + print('\ntls_module_report_test') + os.environ['DEVICE_MAC'] = '68:5e:1c:cb:6e:cb' + startup_pcap_file = os.path.join(CAPTURES_DIR, 'multi_page_startup.pcap') + monitor_pcap_file = os.path.join(CAPTURES_DIR, 'multi_page_monitor.pcap') + tls_pcap_file = os.path.join(CAPTURES_DIR, 'multi_page_tls.pcap') + tls = TLSModule(module=MODULE, + log_dir=OUTPUT_DIR, + results_dir=OUTPUT_DIR, + startup_capture_file=startup_pcap_file, + monitor_capture_file=monitor_pcap_file, + tls_capture_file=tls_pcap_file) + report_out_path = tls.generate_module_report() + with open(report_out_path, 'r', encoding='utf-8') as file: + report_out = file.read() + + # Read the local good report + with open(LOCAL_REPORT, 'r', encoding='utf-8') as file: + report_local = file.read() + + self.assertEqual(report_out, report_local) + def tls_module_report_test(self): print('\ntls_module_report_test') os.environ['DEVICE_MAC'] = '38:d1:35:01:17:fe' @@ -358,7 +381,7 @@ def tls_module_report_test(self): report_out = file.read() # Read the local good report - with open(LOCAL_REPORT, 'r', encoding='utf-8') as file: + with open(LOCAL_REPORT_SINGLE, 'r', encoding='utf-8') as file: report_local = file.read() self.assertEqual(report_out, report_local) @@ -597,13 +620,14 @@ def download_public_cert(self, hostname, port=443): suite.addTest(TLSModuleTest('tls_module_report_test')) suite.addTest(TLSModuleTest('tls_module_report_ext_test')) suite.addTest(TLSModuleTest('tls_module_report_no_cert_test')) + suite.addTest(TLSModuleTest('tls_module_report_multi_page_test')) - # # Test signature validation methods - # suite.addTest(TLSModuleTest('tls_module_trusted_ca_cert_chain_test')) - # suite.addTest(TLSModuleTest('tls_module_local_ca_cert_test')) - # suite.addTest(TLSModuleTest('tls_module_ca_cert_spaces_test')) + # Test signature validation methods + suite.addTest(TLSModuleTest('tls_module_trusted_ca_cert_chain_test')) + suite.addTest(TLSModuleTest('tls_module_local_ca_cert_test')) + suite.addTest(TLSModuleTest('tls_module_ca_cert_spaces_test')) - # suite.addTest(TLSModuleTest('security_tls_client_allowed_protocols_test')) + suite.addTest(TLSModuleTest('security_tls_client_allowed_protocols_test')) suite.addTest(TLSModuleTest('outbound_connections_test')) suite.addTest(TLSModuleTest('outbound_connections_report_test')) From 8d5d18b2a0ebcf77218d48657cdacf912eaf29b8 Mon Sep 17 00:00:00 2001 From: jhughesbiot Date: Mon, 28 Oct 2024 16:58:30 -0600 Subject: [PATCH 10/25] fix unit tests --- .../tls/reports/tls_report_ext_local.html | 113 ++++++++- .../unit/tls/reports/tls_report_local.html | 104 ++++----- .../tls/reports/tls_report_local_single.html | 103 -------- .../unit/tls/reports/tls_report_single.html | 219 ++++++++++++++++++ testing/unit/tls/tls_module_test.py | 12 +- 5 files changed, 394 insertions(+), 157 deletions(-) delete mode 100644 testing/unit/tls/reports/tls_report_local_single.html create mode 100644 testing/unit/tls/reports/tls_report_single.html diff --git a/testing/unit/tls/reports/tls_report_ext_local.html b/testing/unit/tls/reports/tls_report_ext_local.html index bf8193391..a9b182c55 100644 --- a/testing/unit/tls/reports/tls_report_ext_local.html +++ b/testing/unit/tls/reports/tls_report_ext_local.html @@ -1,5 +1,103 @@

TLS Module

+ + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2027-07-25 15:33:09888EC443Sub CA
+ +
+
+
Certificate Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version3 (0x2)
Signature Alg.sha256WithRSAEncryption
Validity from2022-07-26 15:33:09
Valid to2027-07-25 15:33:09
+ +
+
+
Subject Information
+ + + + + + + + + + + + + + + + + + + + +
PropertyValue
CUS
CNapc27D605.nam.gad.schneider-electric.com
+
+
+ + +
Certificate Extensions
+ + + + + + + + + + + + + + +
PropertyValue
subjectAltNameap9643_qa1941270129.nam.gad.schneider-electric.com
+ @@ -97,4 +195,17 @@
Certificate Extensions
-
\ No newline at end of file + +

Outbound Connections

+ + + + + + + + + + +
Destination IPPort
+ \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_local.html b/testing/unit/tls/reports/tls_report_local.html index 688429e92..5433036a7 100644 --- a/testing/unit/tls/reports/tls_report_local.html +++ b/testing/unit/tls/reports/tls_report_local.html @@ -13,11 +13,11 @@

TLS Module

- 2119-02-05 00:00:00 - 619 + 2049-12-31 23:59:59 + 779 EC - 443 - AthenaProcessor685E1CCB6ECB + 47188 + None @@ -40,15 +40,15 @@
Certificate Information
Signature Alg. - ecdsa-with-SHA256 + sha256WithRSAEncryption Validity from - 2019-03-01 00:00:00 + 2023-03-29 18:37:51 Valid to - 2119-02-05 00:00:00 + 2049-12-31 23:59:59 @@ -87,7 +87,7 @@
Subject Information
CN - IPLServer4E580B9 + athena04E580B9 @@ -106,23 +106,23 @@
Certificate Extensions
- keyUsage - digital_signature=True, key_cert_sign=False, key_encipherment=True, crl_sign=False + authorityKeyIdentifier + key_identifier=accca4f9bd2a47dae81a8f4c87ed2c8edcfd07bf, authority_cert_issuer=None, authority_cert_serial_number=None - extendedKeyUsage - serverAuth, Unknown OID + subjectKeyIdentifier + digest=37d90a274635e963081520f98411bda240d30252 - authorityKeyIdentifier - key_identifier=dff100033b0ab36497bbcd2f3e0515ea7b2f7ea0, authority_cert_issuer=None, authority_cert_serial_number=None + basicConstraints + ca=False, path_length=None - subjectAltName - IPLServer4E580B9 + keyUsage + digital_signature=True, key_cert_sign=False, key_encipherment=False, crl_sign=False @@ -145,7 +145,7 @@
Certificate Extensions
2049-12-31 23:59:59 779 EC - 47188 + 35288 None @@ -272,11 +272,11 @@
Certificate Extensions
- 2049-12-31 23:59:59 - 779 + 2119-02-05 00:00:00 + 619 EC - 35288 - None + 443 + AthenaProcessor685E1CCB6ECB @@ -299,15 +299,15 @@
Certificate Information
Signature Alg. - sha256WithRSAEncryption + ecdsa-with-SHA256 Validity from - 2023-03-29 18:37:51 + 2019-03-01 00:00:00 Valid to - 2049-12-31 23:59:59 + 2119-02-05 00:00:00 @@ -346,7 +346,7 @@
Subject Information
CN - athena04E580B9 + IPLServer4E580B9 @@ -365,23 +365,23 @@
Certificate Extensions
- authorityKeyIdentifier - key_identifier=accca4f9bd2a47dae81a8f4c87ed2c8edcfd07bf, authority_cert_issuer=None, authority_cert_serial_number=None + keyUsage + digital_signature=True, key_cert_sign=False, key_encipherment=True, crl_sign=False - subjectKeyIdentifier - digest=37d90a274635e963081520f98411bda240d30252 + extendedKeyUsage + serverAuth, Unknown OID - basicConstraints - ca=False, path_length=None + authorityKeyIdentifier + key_identifier=dff100033b0ab36497bbcd2f3e0515ea7b2f7ea0, authority_cert_issuer=None, authority_cert_serial_number=None - keyUsage - digital_signature=True, key_cert_sign=False, key_encipherment=False, crl_sign=False + subjectAltName + IPLServer4E580B9 @@ -402,11 +402,11 @@
Certificate Extensions
- 2119-02-05 00:00:00 - 619 + 2049-12-31 23:59:59 + 779 EC - 443 - AthenaProcessor685E1CCB6ECB + 47188 + None @@ -429,15 +429,15 @@
Certificate Information
Signature Alg. - ecdsa-with-SHA256 + sha256WithRSAEncryption Validity from - 2019-03-01 00:00:00 + 2023-03-29 18:37:51 Valid to - 2119-02-05 00:00:00 + 2049-12-31 23:59:59 @@ -476,7 +476,7 @@
Subject Information
CN - IPLServer4E580B9 + athena04E580B9 @@ -495,23 +495,23 @@
Certificate Extensions
- keyUsage - digital_signature=True, key_cert_sign=False, key_encipherment=True, crl_sign=False + authorityKeyIdentifier + key_identifier=accca4f9bd2a47dae81a8f4c87ed2c8edcfd07bf, authority_cert_issuer=None, authority_cert_serial_number=None - extendedKeyUsage - serverAuth, Unknown OID + subjectKeyIdentifier + digest=37d90a274635e963081520f98411bda240d30252 - authorityKeyIdentifier - key_identifier=dff100033b0ab36497bbcd2f3e0515ea7b2f7ea0, authority_cert_issuer=None, authority_cert_serial_number=None + basicConstraints + ca=False, path_length=None - subjectAltName - IPLServer4E580B9 + keyUsage + digital_signature=True, key_cert_sign=False, key_encipherment=False, crl_sign=False @@ -526,12 +526,12 @@

Outbound Connections

224.0.0.2515353 - 34.226.101.2528883 209.244.0.3Unknown - 52.94.225.110443 - 3.227.203.88443 3.227.250.136443 + 3.227.203.88443 + 34.226.101.2528883 3.227.250.208443 + 52.94.225.110443 \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_local_single.html b/testing/unit/tls/reports/tls_report_local_single.html deleted file mode 100644 index beef934d3..000000000 --- a/testing/unit/tls/reports/tls_report_local_single.html +++ /dev/null @@ -1,103 +0,0 @@ -

TLS Module

- - - - - - - - - - - - - - - - - - - - - - -
ExpiryLengthTypePort numberSigned by
2027-09-21 19:57:57901RSA443BuildingsIoT RSA Signing CA
- -
-
-
Certificate Information
- - - - - - - - - - - - - - - - - - - - - - - - - - -
PropertyValue
Version1 (0x0)
Signature Alg.sha256WithRSAEncryption
Validity from2022-09-21 19:57:57
Valid to2027-09-21 19:57:57
- -
-
-
Subject Information
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PropertyValue
CUS
STCalifornia
LConcord
OBuildingsIoT
OUSoftware
CNEasyIO_FS-32
-
-
- diff --git a/testing/unit/tls/reports/tls_report_single.html b/testing/unit/tls/reports/tls_report_single.html new file mode 100644 index 000000000..0fb8a7d65 --- /dev/null +++ b/testing/unit/tls/reports/tls_report_single.html @@ -0,0 +1,219 @@ +

TLS Module

+ + + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2027-09-21 19:57:57901RSA443BuildingsIoT RSA Signing CA
+ +
+
+
Certificate Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version1 (0x0)
Signature Alg.sha256WithRSAEncryption
Validity from2022-09-21 19:57:57
Valid to2027-09-21 19:57:57
+ +
+
+
Subject Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
CUS
STCalifornia
LConcord
OBuildingsIoT
OUSoftware
CNEasyIO_FS-32
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
ExpiryLengthTypePort numberSigned by
2027-09-21 19:57:57901RSA443BuildingsIoT RSA Signing CA
+ +
+
+
Certificate Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
Version1 (0x0)
Signature Alg.sha256WithRSAEncryption
Validity from2022-09-21 19:57:57
Valid to2027-09-21 19:57:57
+ +
+
+
Subject Information
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyValue
CUS
STCalifornia
LConcord
OBuildingsIoT
OUSoftware
CNEasyIO_FS-32
+
+
+ + +

Outbound Connections

+ + + + + + + + + + +
Destination IPPort
+ \ No newline at end of file diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index d51ac167e..424977323 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -329,10 +329,20 @@ def outbound_connections_test(self): ip_dst = TLS_UTIL.get_all_outbound_connections( device_mac='70:b3:d5:96:c0:00', capture_files=[capture_file]) print(str(ip_dst)) + # Expected set of IPs and ports in tuple format + expected_ips = { + ('216.239.35.0', 123), + ('8.8.8.8', 'Unknown'), + ('8.8.8.8', 53), + ('18.140.82.197', 443), + ('18.140.82.197', 22), + ('224.0.0.22', 'Unknown'), + ('18.140.82.197', 80) + } # Compare as sets since returned order is not guaranteed self.assertEqual( set(ip_dst), - set(['8.8.8.8', '224.0.0.22', '18.140.82.197', '216.239.35.0'])) + expected_ips) def outbound_connections_report_test(self): """ Test generation of the outbound connection ips""" From fb12257adf5cd9aec615bb1cd1a8c0844e8fd3e8 Mon Sep 17 00:00:00 2001 From: jhughesbiot Date: Mon, 28 Oct 2024 17:06:07 -0600 Subject: [PATCH 11/25] pylint --- testing/unit/tls/tls_module_test.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index 424977323..bffe64515 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -361,7 +361,6 @@ def tls_module_report_multi_page_test(self): monitor_pcap_file = os.path.join(CAPTURES_DIR, 'multi_page_monitor.pcap') tls_pcap_file = os.path.join(CAPTURES_DIR, 'multi_page_tls.pcap') tls = TLSModule(module=MODULE, - log_dir=OUTPUT_DIR, results_dir=OUTPUT_DIR, startup_capture_file=startup_pcap_file, monitor_capture_file=monitor_pcap_file, @@ -401,7 +400,6 @@ def tls_module_report_ext_test(self): os.environ['DEVICE_MAC'] = '28:29:86:27:d6:05' pcap_file = os.path.join(CAPTURES_DIR, 'tls_ext.pcap') tls = TLSModule(module=MODULE, - log_dir=OUTPUT_DIR, results_dir=OUTPUT_DIR, startup_capture_file=pcap_file, monitor_capture_file=pcap_file, @@ -428,7 +426,6 @@ def tls_module_report_no_cert_test(self): os.environ['DEVICE_MAC'] = '' pcap_file = os.path.join(CAPTURES_DIR, 'tls_ext.pcap') tls = TLSModule(module=MODULE, - log_dir=OUTPUT_DIR, results_dir=OUTPUT_DIR, startup_capture_file=pcap_file, monitor_capture_file=pcap_file, From 950b694895c5f4205f3ef791cd27d037c7bf6ef1 Mon Sep 17 00:00:00 2001 From: jhughesbiot Date: Mon, 28 Oct 2024 17:07:39 -0600 Subject: [PATCH 12/25] pylint --- testing/unit/tls/tls_module_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index bffe64515..f0ad30014 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -380,7 +380,6 @@ def tls_module_report_test(self): os.environ['DEVICE_MAC'] = '38:d1:35:01:17:fe' pcap_file = os.path.join(CAPTURES_DIR, 'tls.pcap') tls = TLSModule(module=MODULE, - log_dir=OUTPUT_DIR, results_dir=OUTPUT_DIR, startup_capture_file=pcap_file, monitor_capture_file=pcap_file, From e74b33fa135d8528117b4aa426aebfd001fbe1ec Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 12:04:24 +0000 Subject: [PATCH 13/25] Add additional device config info and generate pdf --- .../device_configs/tester1/device_config.json | 31 ++++++++++++++++++- .../device_configs/tester2/device_config.json | 31 ++++++++++++++++++- .../device_configs/tester3/device_config.json | 31 ++++++++++++++++++- testing/unit/report/report_test.py | 8 +++-- 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/testing/device_configs/tester1/device_config.json b/testing/device_configs/tester1/device_config.json index f9eeccb6a..0c94febd2 100644 --- a/testing/device_configs/tester1/device_config.json +++ b/testing/device_configs/tester1/device_config.json @@ -2,6 +2,9 @@ "manufacturer": "Google", "model": "Tester 1", "mac_addr": "02:42:aa:00:00:01", + "type": "Controller - FCU", + "technology": "Hardware - Fitness", + "test_pack": "Device Qualification", "test_modules": { "dns": { "enabled": true @@ -24,5 +27,31 @@ "tls": { "enabled": false } - } + }, + "additional_info": [ + { + "question": "What type of device is this?", + "answer": "Controller - FCU" + }, + { + "question": "Please select the technology this device falls into", + "answer": "Hardware - Fitness" + }, + { + "question": "Does your device process any sensitive information? ", + "answer": "No" + }, + { + "question": "Can all non-essential services be disabled on your device?", + "answer": "Yes" + }, + { + "question": "Is there a second IP port on the device?", + "answer": "No" + }, + { + "question": "Can the second IP port on your device be disabled?", + "answer": "N/A" + } + ] } diff --git a/testing/device_configs/tester2/device_config.json b/testing/device_configs/tester2/device_config.json index ccbc14585..d816cb2ef 100644 --- a/testing/device_configs/tester2/device_config.json +++ b/testing/device_configs/tester2/device_config.json @@ -2,6 +2,9 @@ "manufacturer": "Google", "model": "Tester 2", "mac_addr": "02:42:aa:00:00:02", + "type": "Controller - FCU", + "technology": "Hardware - Fitness", + "test_pack": "Device Qualification", "test_modules": { "dns": { "enabled": true @@ -24,5 +27,31 @@ "tls": { "enabled": false } - } + }, + "additional_info": [ + { + "question": "What type of device is this?", + "answer": "Controller - FCU" + }, + { + "question": "Please select the technology this device falls into", + "answer": "Hardware - Fitness" + }, + { + "question": "Does your device process any sensitive information? ", + "answer": "No" + }, + { + "question": "Can all non-essential services be disabled on your device?", + "answer": "Yes" + }, + { + "question": "Is there a second IP port on the device?", + "answer": "No" + }, + { + "question": "Can the second IP port on your device be disabled?", + "answer": "N/A" + } + ] } diff --git a/testing/device_configs/tester3/device_config.json b/testing/device_configs/tester3/device_config.json index b7792027e..7b0206ca3 100644 --- a/testing/device_configs/tester3/device_config.json +++ b/testing/device_configs/tester3/device_config.json @@ -2,6 +2,9 @@ "manufacturer": "Google", "model": "Tester 3", "mac_addr": "02:42:aa:00:00:03", + "type": "Controller - FCU", + "technology": "Hardware - Fitness", + "test_pack": "Device Qualification", "test_modules": { "dns": { "enabled": false @@ -18,5 +21,31 @@ "nmap": { "enabled": false } - } + }, + "additional_info": [ + { + "question": "What type of device is this?", + "answer": "Controller - FCU" + }, + { + "question": "Please select the technology this device falls into", + "answer": "Hardware - Fitness" + }, + { + "question": "Does your device process any sensitive information? ", + "answer": "No" + }, + { + "question": "Can all non-essential services be disabled on your device?", + "answer": "Yes" + }, + { + "question": "Is there a second IP port on the device?", + "answer": "No" + }, + { + "question": "Can the second IP port on your device be disabled?", + "answer": "N/A" + } + ] } diff --git a/testing/unit/report/report_test.py b/testing/unit/report/report_test.py index 4222c6d46..16ca61dd0 100644 --- a/testing/unit/report/report_test.py +++ b/testing/unit/report/report_test.py @@ -71,12 +71,16 @@ def create_report(self, results_file_path): # Create the HTML filename based on the JSON name file_name = os.path.splitext(os.path.basename(results_file_path))[0] - report_out_file = os.path.join(OUTPUT_DIR, file_name + '.html') + report_html_file = os.path.join(OUTPUT_DIR, file_name + '.html') + report_pdf_file = os.path.join(OUTPUT_DIR, file_name + '.pdf') # Save report as HTML file - with open(report_out_file, 'w', encoding='utf-8') as file: + with open(report_html_file, 'w', encoding='utf-8') as file: file.write(report.to_html()) + with open(report_pdf_file, 'w', encoding='utf-8') as file: + file.write(report.to_pdf()) + def report_compliant_test(self): """Generate a report for the compliant test""" From 4427ff5051fd8e35c814e909792e4566c9a4259f Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 12:32:47 +0000 Subject: [PATCH 14/25] Fix pdf report generation --- testing/unit/report/report_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/unit/report/report_test.py b/testing/unit/report/report_test.py index 16ca61dd0..b4925da12 100644 --- a/testing/unit/report/report_test.py +++ b/testing/unit/report/report_test.py @@ -79,7 +79,7 @@ def create_report(self, results_file_path): file.write(report.to_html()) with open(report_pdf_file, 'w', encoding='utf-8') as file: - file.write(report.to_pdf()) + file.write(report.to_pdf().get_value()) def report_compliant_test(self): """Generate a report for the compliant test""" From f8951551b1b6726f8c04ea0946ffd2295d6cc4da Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 13:02:50 +0000 Subject: [PATCH 15/25] Fix pdf get value --- .github/workflows/testing.yml | 9 +++------ testing/unit/report/report_test.py | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index b14f52c9f..9ba417f9f 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -97,16 +97,13 @@ jobs: - name: Run tests for reports shell: bash {0} run: bash testing/unit/run_report_test.sh testing/unit/report/report_test.py - - name: Archive HTML reports for modules - if: ${{ always() }} - run: sudo tar --exclude-vcs -czf html_reports.tgz testing/unit/report/output/ - - name: Upload HTML reports + - name: Upload reports uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 if: ${{ always() }} with: if-no-files-found: error - name: html-reports_${{ github.run_id }} - path: html_reports.tgz + name: reports_${{ github.run_id }} + path: testing/unit/report/output pylint: permissions: {} diff --git a/testing/unit/report/report_test.py b/testing/unit/report/report_test.py index b4925da12..ef06d9286 100644 --- a/testing/unit/report/report_test.py +++ b/testing/unit/report/report_test.py @@ -79,7 +79,7 @@ def create_report(self, results_file_path): file.write(report.to_html()) with open(report_pdf_file, 'w', encoding='utf-8') as file: - file.write(report.to_pdf().get_value()) + file.write(report.to_pdf().getvalue()) def report_compliant_test(self): """Generate a report for the compliant test""" From f4f435842a11d1ace3a42f835b861ab7faba32a4 Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 13:09:31 +0000 Subject: [PATCH 16/25] Open file as binary --- testing/unit/report/report_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/unit/report/report_test.py b/testing/unit/report/report_test.py index ef06d9286..8e8767185 100644 --- a/testing/unit/report/report_test.py +++ b/testing/unit/report/report_test.py @@ -78,7 +78,7 @@ def create_report(self, results_file_path): with open(report_html_file, 'w', encoding='utf-8') as file: file.write(report.to_html()) - with open(report_pdf_file, 'w', encoding='utf-8') as file: + with open(report_pdf_file, 'wb', encoding='utf-8') as file: file.write(report.to_pdf().getvalue()) def report_compliant_test(self): From b6d65c88420d0458292dda257446de186760efbb Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 13:15:47 +0000 Subject: [PATCH 17/25] Fix error --- testing/unit/report/report_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/unit/report/report_test.py b/testing/unit/report/report_test.py index 8e8767185..f706059b6 100644 --- a/testing/unit/report/report_test.py +++ b/testing/unit/report/report_test.py @@ -78,7 +78,7 @@ def create_report(self, results_file_path): with open(report_html_file, 'w', encoding='utf-8') as file: file.write(report.to_html()) - with open(report_pdf_file, 'wb', encoding='utf-8') as file: + with open(report_pdf_file, 'wb') as file: file.write(report.to_pdf().getvalue()) def report_compliant_test(self): From cfa4c76debc94da0b2e35ece5952296cc37ea0d9 Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 13:28:29 +0000 Subject: [PATCH 18/25] Fix some formatting --- modules/test/tls/python/src/tls_module.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index 2000e5abb..9b79a3f27 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -182,7 +182,7 @@ def generate_module_report(self): ext_table = '''
Certificate Extensions
- +
@@ -230,7 +230,7 @@ def generate_module_report(self): summary_table += f'''
-
+
Certificate Information
{cert_table}
From f77ea0c19945ca0126084b0192a76b22d16bf432 Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 13:42:26 +0000 Subject: [PATCH 19/25] Update expected reports --- .../tls/reports/tls_report_ext_local.html | 11 ++++++----- .../unit/tls/reports/tls_report_local.html | 19 ++++++++++--------- .../unit/tls/reports/tls_report_single.html | 7 ++++--- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/testing/unit/tls/reports/tls_report_ext_local.html b/testing/unit/tls/reports/tls_report_ext_local.html index a9b182c55..7e691f66a 100644 --- a/testing/unit/tls/reports/tls_report_ext_local.html +++ b/testing/unit/tls/reports/tls_report_ext_local.html @@ -23,7 +23,7 @@

TLS Module

Property
-
+
Certificate Information
@@ -82,7 +82,7 @@
Subject Information
Certificate Extensions
-
+
@@ -122,7 +122,7 @@
Certificate Extensions
Property
-
+
Certificate Information
@@ -181,7 +181,7 @@
Subject Information
Certificate Extensions
-
+
@@ -207,5 +207,6 @@

Outbound Connections

-
Property
+ + \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_local.html b/testing/unit/tls/reports/tls_report_local.html index 5433036a7..15f4d0283 100644 --- a/testing/unit/tls/reports/tls_report_local.html +++ b/testing/unit/tls/reports/tls_report_local.html @@ -23,7 +23,7 @@

TLS Module

-
+
Certificate Information
@@ -97,7 +97,7 @@
Subject Information
Certificate Extensions
-
+
@@ -152,7 +152,7 @@
Certificate Extensions
Property
-
+
Certificate Information
@@ -226,7 +226,7 @@
Subject Information
Certificate Extensions
-
+
@@ -282,7 +282,7 @@
Certificate Extensions
Property
-
+
Certificate Information
@@ -356,7 +356,7 @@
Subject Information
Certificate Extensions
-
+
@@ -412,7 +412,7 @@
Certificate Extensions
Property
-
+
Certificate Information
@@ -486,7 +486,7 @@
Subject Information
Certificate Extensions
-
+
@@ -533,5 +533,6 @@

Outbound Connections

-
Property
3.227.250.208443
52.94.225.110443
+ + \ No newline at end of file diff --git a/testing/unit/tls/reports/tls_report_single.html b/testing/unit/tls/reports/tls_report_single.html index 0fb8a7d65..36adffb94 100644 --- a/testing/unit/tls/reports/tls_report_single.html +++ b/testing/unit/tls/reports/tls_report_single.html @@ -23,7 +23,7 @@

TLS Module

-
+
Certificate Information
@@ -126,7 +126,7 @@
Subject Information
-
+
Certificate Information
@@ -215,5 +215,6 @@

Outbound Connections

-
+ + \ No newline at end of file From 4592ea7bc923c8a92067554e95ef297837b96ca6 Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 14:01:25 +0000 Subject: [PATCH 20/25] Fix formatting --- modules/test/tls/python/src/tls_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index 9b79a3f27..1405ad31c 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -230,7 +230,7 @@ def generate_module_report(self): summary_table += f'''
-
+
Certificate Information
{cert_table}
From d5de670b2a1f1c68edbe08bbfec872641f858966 Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 14:06:43 +0000 Subject: [PATCH 21/25] Fix report test --- testing/unit/tls/reports/tls_report_local.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/unit/tls/reports/tls_report_local.html b/testing/unit/tls/reports/tls_report_local.html index 15f4d0283..72b2e5a1a 100644 --- a/testing/unit/tls/reports/tls_report_local.html +++ b/testing/unit/tls/reports/tls_report_local.html @@ -23,7 +23,7 @@

TLS Module

-
+
Certificate Information
From 8fcbda4a1c18267a3ab6deb931ace23c31e06c38 Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Fri, 22 Nov 2024 14:47:18 +0000 Subject: [PATCH 22/25] Add additional info to test devices --- testing/unit/report/report_compliant.json | 31 +++++++++++++++++++- testing/unit/report/report_noncompliant.json | 31 +++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/testing/unit/report/report_compliant.json b/testing/unit/report/report_compliant.json index 08ff585ad..6b84a8d39 100644 --- a/testing/unit/report/report_compliant.json +++ b/testing/unit/report/report_compliant.json @@ -4,6 +4,9 @@ "manufacturer": "Testrun", "model": "Faux", "firmware": "1.0.0", + "type": "Controller - FCU", + "technology": "Hardware - Fitness", + "test_pack": "Device Qualification", "test_modules": { "connection": { "enabled": true @@ -23,7 +26,33 @@ "protocol": { "enabled": true } - } + }, + "additional_info": [ + { + "question": "What type of device is this?", + "answer": "Controller - FCU" + }, + { + "question": "Please select the technology this device falls into", + "answer": "Hardware - Fitness" + }, + { + "question": "Does your device process any sensitive information? ", + "answer": "No" + }, + { + "question": "Can all non-essential services be disabled on your device?", + "answer": "Yes" + }, + { + "question": "Is there a second IP port on the device?", + "answer": "No" + }, + { + "question": "Can the second IP port on your device be disabled?", + "answer": "N/A" + } + ] }, "status": "Compliant", "started": "2024-04-10 21:21:47", diff --git a/testing/unit/report/report_noncompliant.json b/testing/unit/report/report_noncompliant.json index b3ba74c0d..6619bba19 100644 --- a/testing/unit/report/report_noncompliant.json +++ b/testing/unit/report/report_noncompliant.json @@ -4,6 +4,9 @@ "manufacturer": "Testrun", "model": "Faux", "firmware": "1.0.0", + "type": "Controller - FCU", + "technology": "Hardware - Fitness", + "test_pack": "Device Qualification", "test_modules": { "connection": { "enabled": true @@ -23,7 +26,33 @@ "protocol": { "enabled": true } - } + }, + "additional_info": [ + { + "question": "What type of device is this?", + "answer": "Controller - FCU" + }, + { + "question": "Please select the technology this device falls into", + "answer": "Hardware - Fitness" + }, + { + "question": "Does your device process any sensitive information? ", + "answer": "No" + }, + { + "question": "Can all non-essential services be disabled on your device?", + "answer": "Yes" + }, + { + "question": "Is there a second IP port on the device?", + "answer": "No" + }, + { + "question": "Can the second IP port on your device be disabled?", + "answer": "N/A" + } + ] }, "status": "Non-Compliant", "started": "2024-04-10 21:21:47", From faf9090cd794ed323e2b22c57d574de59dece150 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 27 Nov 2024 12:42:42 +0100 Subject: [PATCH 23/25] beautifulsoup --- framework/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/requirements.txt b/framework/requirements.txt index 6f54d3a99..82624b03b 100644 --- a/framework/requirements.txt +++ b/framework/requirements.txt @@ -42,3 +42,4 @@ APScheduler==3.10.4 # Requirements for reports generation Jinja2==3.1.4 +beautifulsoup4==4.12.3 \ No newline at end of file From e87bad7605f3c911333f73aa50cf7373742795f3 Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 27 Nov 2024 12:43:16 +0100 Subject: [PATCH 24/25] refactor splitting module reports to pages --- framework/python/src/common/testreport.py | 147 ++++++++++++++-------- 1 file changed, 94 insertions(+), 53 deletions(-) diff --git a/framework/python/src/common/testreport.py b/framework/python/src/common/testreport.py index f9401fe80..53ef2dc03 100644 --- a/framework/python/src/common/testreport.py +++ b/framework/python/src/common/testreport.py @@ -23,6 +23,9 @@ from test_orc.test_case import TestCase from jinja2 import Environment, FileSystemLoader from collections import OrderedDict +import re +from bs4 import BeautifulSoup + DATE_TIME_FORMAT = '%Y-%m-%d %H:%M:%S' RESOURCES_DIR = 'resources/report' @@ -330,12 +333,37 @@ def _get_optional_steps_to_resolve(self, json_data): return tests_with_recommendations + + def _split_module_report_to_pages(self, reports): + """Split report to pages by headers""" + reports_transformed = [] + + for report in reports: + if len(re.findall('
1: + indices = [] + index = report.find('
' in line and data_table_active: - data_table_active=False - - # Add module-data header size, ignore rows, should - # only be one so only care about a header existence - elif '' in line and data_table_active: - content_size += 41.333 - - # Track module-data table state - elif '' in line and data_table_active: - data_rows_active = True - elif '' in line and data_rows_active: - data_rows_active = False - - # Add appropriate content size for each data row - # update if CSS changes for this element - elif '' in line and data_rows_active: - content_size += 42 - - # If the current line is within the content size limit - # we'll add it to this page, otherweise, we'll put it on the next - # page. Also make sure that if there is less than 40 pixels - # left after a data row, start a new page or the row will get cut off. - # Current row size is 42 # adjust if we update the - # "module-data tbody tr" element. - if content_size >= content_max_size or ( - data_rows_active and content_max_size - content_size < 42): - # If in the middle of a table, close the table - if data_rows_active: - page_content += '
' - reports.append(page_content) - content_size = 0 - # If in the middle of a data table, restart - # it for the rest of the rows - page_content = ('\n' - if data_rows_active else '') - page_content += line + '\n' - if len(page_content) > 0: - reports.append(page_content) + + # Convert module report to list of html tags + soup = BeautifulSoup(module_report, features='html5lib') + children = list( + filter(lambda el: el.name is not None, soup.body.children) + ) + + for index, el in enumerate(children): + current_size = 0 + if el.name == 'h1': + current_size += 40 + h1_padding + # Calculating the height of paired tables + elif (el.name == 'div' + and el['style'] == 'display:flex;justify-content:space-between;'): + tables = el.findChildren('table', recursive=True) + current_size = max( + map(lambda t: len( + t.findChildren('tr', recursive=True) + ), tables) + ) * 42 + # Table height + elif el.name == 'table': + if el['class'] == 'module-summary': + current_size = 85 + module_summary_padding + else: + current_size = len(el.findChildren('tr', recursive=True)) * 42 + # Other elements height + else: + current_size = 50 + # Moving tables to the next page. + # Completely transfer tables that are within the maximum + # allowable size, while splitting those that exceed the page size. + if (content_size + current_size) >= content_max_size: + str_el = '' + if current_size > (content_max_size - 85 - module_summary_padding): + rows = el.findChildren('tr', recursive=True) + table_header = str(rows.pop(0)) + table_1 = table_2 = f''' +
+ {table_header}''' + rows_count = (content_max_size - 85 - module_summary_padding) // 42 + table_1 += ''.join(map(str, rows[:rows_count-1])) + table_1 += '
' + table_2 += ''.join(map(str, rows[rows_count-1:])) + table_2 += '' + page_content += table_1 + reports.append(page_content) + page_content = table_2 + current_size = len(rows[rows_count:]) * 42 + else: + if el.name == 'table': + el_header = children[index-1] + if el_header.name.startswith('h'): + page_content = ''.join(page_content.rsplit(str(el_header), 1)) + str_el = str(el_header) + str(el) + content_size = current_size + 50 + else: + str_el = str(el) + content_size = current_size + reports.append(page_content) + page_content = str_el + else: + page_content += str(el) + content_size += current_size + reports.append(page_content) return reports From ef6a02b1e930e93ccd05497b77cb969d5a402bce Mon Sep 17 00:00:00 2001 From: Aliaksandr Nikitsin Date: Wed, 27 Nov 2024 23:13:16 +0100 Subject: [PATCH 25/25] style changes --- framework/python/src/common/testreport.py | 10 ++++++++-- resources/report/test_report_styles.css | 13 ++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/framework/python/src/common/testreport.py b/framework/python/src/common/testreport.py index 53ef2dc03..6acc6eac0 100644 --- a/framework/python/src/common/testreport.py +++ b/framework/python/src/common/testreport.py @@ -347,9 +347,15 @@ def _split_module_report_to_pages(self, reports): index = report.find('