From 22b65a9b84af36d8c12c32c6e5c0dae88208ea49 Mon Sep 17 00:00:00 2001 From: AleJo2995 Date: Tue, 15 Aug 2023 07:38:08 -0600 Subject: [PATCH] fix: headings levels validation is not working properly (#1436) * fix: heading levels validation fixing Signed-off-by: Alejandro Jose Leiva Palomo * fix: correcting test cases and adding extra validation Signed-off-by: Alejandro Jose Leiva Palomo --------- Signed-off-by: Alejandro Jose Leiva Palomo --- .../bad_instance_reordered.md | 23 -------- .../architecture.md | 59 +++++++++++++++++++ .../architecture.md | 30 ++++++++++ .../core/commands/author/folders_test.py | 24 ++++++++ .../core/markdown/markdown_validator_test.py | 14 ----- trestle/core/markdown/markdown_validator.py | 22 +++---- 6 files changed, 122 insertions(+), 50 deletions(-) delete mode 100644 tests/data/author/0.0.1/test_1_md_format/bad_instance_reordered.md create mode 100644 tests/data/author/governed_folders/instance_with_diff_heading_levels/architecture.md create mode 100644 tests/data/author/governed_folders/template_folder_headling_levels/architecture.md diff --git a/tests/data/author/0.0.1/test_1_md_format/bad_instance_reordered.md b/tests/data/author/0.0.1/test_1_md_format/bad_instance_reordered.md deleted file mode 100644 index 545c9cc2e..000000000 --- a/tests/data/author/0.0.1/test_1_md_format/bad_instance_reordered.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -yaml: header ---- - -# Required header 1 - -Here is stuff I need to write. - -# Required header 3 - -This is out of order - -# Required header 2 - -Here is stuff I need to write. - -## Required sub-header 1 - -Here is stuff I need to write. - -## Required sub-header 2 - -Here is stuff I need to write. diff --git a/tests/data/author/governed_folders/instance_with_diff_heading_levels/architecture.md b/tests/data/author/governed_folders/instance_with_diff_heading_levels/architecture.md new file mode 100644 index 000000000..0863b79e1 --- /dev/null +++ b/tests/data/author/governed_folders/instance_with_diff_heading_levels/architecture.md @@ -0,0 +1,59 @@ +--- +authors: + - Tim + - Jane + - Sally +owner: Joe +valid: + from: 2020-01-01 + to: 2099-12-31 +--- + +# Vulnerability Management (VULN) Defect Checks +## 0. Vulnerability Management Workflow +### 0.1 Data Sources +### 0.2 Fetchers +### 0.3 Data Store +### 0.4 Policy Engine +### 0.5 Ticketing System +## 1. Facts Data Model +### 1.1 Devices +#### Server +#### KubernetesCluster +#### ContainerImage +### 1.2 Vulnerabilities +#### ResourceScan +#### ResourceScanFinding +#### ResourceScanResult +### 1.3 Thresholds +#### CISOOverride +#### CISAKEV +### 1.4 Risks +#### VulnDeviations +### 1.5 Scanner Definition +#### ScannerConfiguration +## 2. Defect Checks +### Sub-capability: Reduce Software/ Firmware Vulnerabilities +#### Vulnerable Software/ Firmware +##### Purpose +##### Assessment Criteria +###### Inputs +###### Rules +####### vuln_prod_os_scan_duedate_check +######## Type +######## Rationale Statement +######## Impact Statement +######## Implementation Description +######## Audit Procedure(s) +######## Remediation Procedure(s) +######## Parameters +####### vuln_prod_os_scan_warning_duedate_check_warning +######## Type +######## Rationale Statement +######## Impact Statement +######## Implementation Description +######## Audit Procedure(s) +######## Remediation Procedure(s) +######## Parameters +###### Additional Outputs +##### Assessment Objectives diff --git a/tests/data/author/governed_folders/template_folder_headling_levels/architecture.md b/tests/data/author/governed_folders/template_folder_headling_levels/architecture.md new file mode 100644 index 000000000..e633a3061 --- /dev/null +++ b/tests/data/author/governed_folders/template_folder_headling_levels/architecture.md @@ -0,0 +1,30 @@ +--- +authors: + - Tim + - Jane + - Sally +owner: Joe +valid: + from: 2020-01-01 + to: 2099-12-31 +--- + +# { Security Capability Name } Defect Checks +## 1. Facts Data Model +### Sub-Capability: { _insert name of subcapability_} +## 2. Defect Checks +### Sub-capability: { _insert sub-capability name_} +#### { _insert defect check name_} +##### Assessment Criteria +###### Inputs +###### Rules +####### { Rule Name} +######## Type +######## Rationale Statement +######## Impact Statement +######## Implementation Description +######## Audit Procedure(s) +######## Remediation Procedure(s) +######## Parameters +###### Additional Outputs +##### Assessment Objectives \ No newline at end of file diff --git a/tests/trestle/core/commands/author/folders_test.py b/tests/trestle/core/commands/author/folders_test.py index 4e7d2d2e7..cd47e9f5e 100644 --- a/tests/trestle/core/commands/author/folders_test.py +++ b/tests/trestle/core/commands/author/folders_test.py @@ -674,3 +674,27 @@ def test_drawio_versioning_validation( monkeypatch.setattr(sys, 'argv', command_string_validate_content.split()) rc = trestle.cli.Trestle().run() assert rc == 0 + + +def test_heading_levels_hierarchy( + testdata_dir: pathlib.Path, tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch +) -> None: + """Test behaviour when validating drawio instance.""" + task_template_folder = tmp_trestle_dir / '.trestle/author/test_task/' + test_template_folder = testdata_dir / 'author/governed_folders/template_folder_headling_levels' + test_instances_folder = testdata_dir / 'author/governed_folders/instance_with_diff_heading_levels' + task_instance_folder = tmp_trestle_dir / 'test_task/folder_1' + + hidden_file = testdata_dir / pathlib.Path( + 'author/governed_folders/template_folder_with_drawio/.hidden_does_not_affect' + ) + test_utils.make_file_hidden(hidden_file) + + test_utils.copy_tree_or_file_with_hidden(test_template_folder, task_template_folder) + + shutil.copytree(test_instances_folder, task_instance_folder) + + command_string_validate_content = 'trestle author folders validate -tn test_task -hv' + monkeypatch.setattr(sys, 'argv', command_string_validate_content.split()) + rc = trestle.cli.Trestle().run() + assert rc == 0 diff --git a/tests/trestle/core/markdown/markdown_validator_test.py b/tests/trestle/core/markdown/markdown_validator_test.py index 86ca09546..ada27a8ee 100644 --- a/tests/trestle/core/markdown/markdown_validator_test.py +++ b/tests/trestle/core/markdown/markdown_validator_test.py @@ -55,13 +55,6 @@ False, False ), - ( - pathlib.Path('tests/data/author/0.0.1/test_1_md_format/template.md'), - pathlib.Path('tests/data/author/0.0.1/test_1_md_format/bad_instance_reordered.md'), - False, - False, - False - ), ( pathlib.Path('tests/data/author/0.0.1/test_1_md_format/template.md'), pathlib.Path('tests/data/author/0.0.1/test_1_md_format/bad_instance_missing_heading.md'), @@ -125,13 +118,6 @@ False, False ), - ( - pathlib.Path('tests/data/author/0.0.1/test_4_md_format_extras/template.md'), - pathlib.Path('tests/data/author/0.0.1/test_4_md_format_extras/bad_instance_reordered.md'), - False, - False, - False - ), ( pathlib.Path('tests/data/author/0.0.1/test_4_md_format_extras/template.md'), pathlib.Path('tests/data/author/0.0.1/test_4_md_format_extras/bad_instance_missing_heading.md'), diff --git a/trestle/core/markdown/markdown_validator.py b/trestle/core/markdown/markdown_validator.py index c50f4d647..3cd91cea5 100644 --- a/trestle/core/markdown/markdown_validator.py +++ b/trestle/core/markdown/markdown_validator.py @@ -21,6 +21,7 @@ import trestle.core.markdown.markdown_const as md_const from trestle.common.err import TrestleError +from trestle.common.list_utils import as_list from trestle.core.commands.author.consts import START_TEMPLATE_VERSION, TEMPLATE_VERSION_HEADER from trestle.core.markdown.docs_markdown_node import DocsMarkdownNode @@ -202,30 +203,25 @@ def _validate_headings(self, instance: pathlib.Path, template_keys: List[str], i ) return False template_header_pointer = 0 + present_keys = [] for key in instance_keys: if template_header_pointer >= len(template_keys): break - if key in template_keys and key != template_keys[template_header_pointer]: - logger.warning( - f'Headings in the instance: {instance} were shuffled or modified. ' - f'\nInstance does not have required template heading ' - f'\"{template_keys[template_header_pointer]}\". ' - f'Check if this heading was modified/present in the instance.' - f'\nPlease note that no changes to template headings are allowed, ' - f'including extra spaces.' - ) - return False - elif key in template_keys and key == template_keys[template_header_pointer]: + if key in template_keys and key not in present_keys: + present_keys.append(template_keys[template_keys.index(key)]) template_header_pointer += 1 elif re.search(md_const.SUBSTITUTION_REGEX, template_keys[template_header_pointer]) is not None: + present_keys.append(template_keys[template_header_pointer]) template_header_pointer += 1 # skip headers with substitutions - if template_header_pointer != len(template_keys): + diff_keys = set(template_keys) - set(present_keys) + if template_header_pointer != len(template_keys) and len(diff_keys) > 0: logger.info( f'Headings in the instance: {instance} were removed. ' f'Expected {len(template_keys)} headings, but found only {template_header_pointer}.' ) + for result in as_list(diff_keys): + logger.info(f'Heading {result} in the instance: {instance} was removed or not present ') return False - return True @classmethod