Skip to content

Commit

Permalink
fix: allows inheritance info to be removed when component is unmapped
Browse files Browse the repository at this point in the history
Signed-off-by: Jennifer Power <[email protected]>
  • Loading branch information
jpower432 committed Sep 25, 2023
1 parent 648085d commit 6de26a1
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 12 deletions.
37 changes: 36 additions & 1 deletion tests/trestle/core/crm/exports_reader_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,13 @@ def test_read_inheritance_markdown_dir(tmp_trestle_dir: pathlib.Path) -> None:
reader = exportreader.ExportReader(inheritance_path, orig_ssp) # type: ignore
markdown_dict: exportreader.InheritanceViewDict = reader._read_inheritance_markdown_directory()

assert len(markdown_dict) == 2
assert len(markdown_dict) == 3
assert 'ac-2' in markdown_dict
assert len(markdown_dict['ac-2']) == 2
assert expected_appliance_uuid in markdown_dict['ac-2']

assert len(markdown_dict['ac-2.1']) == 0

inheritance_info = markdown_dict['ac-2'][expected_appliance_uuid]

assert inheritance_info[0][0].provided_uuid == '18ac4e2a-b5f2-46e4-94fa-cc84ab6fe114'
Expand All @@ -166,6 +168,12 @@ def test_read_inheritance_markdown_dir_with_multiple_leveraged_components(tmp_tr
leveraged_statement_names=['Access Control Appliance']
)

unmapped_text = test_utils.generate_test_inheritance_md(
provided_uuid=example_provided_uuid,
responsibility_uuid=example_responsibility_uuid,
leveraged_statement_names=[const.REPLACE_ME]
)

this_system_dir = inheritance_path.joinpath('This System')
ac_2 = this_system_dir.joinpath('ac-2')
ac_2.mkdir(parents=True)
Expand All @@ -174,6 +182,13 @@ def test_read_inheritance_markdown_dir_with_multiple_leveraged_components(tmp_tr
with open(file, 'w') as f:
f.write(inheritance_text_2)

ac_2a = this_system_dir.joinpath('ac-2_smt.a')
ac_2a.mkdir(parents=True)

file = ac_2a / f'{expected_appliance_uuid}.md'
with open(file, 'w') as f:
f.write(unmapped_text)

test_utils.load_from_json(tmp_trestle_dir, 'leveraging_ssp', leveraging_ssp, ossp.SystemSecurityPlan)

orig_ssp, _ = ModelUtils.load_model_for_class(
Expand All @@ -195,6 +210,16 @@ def test_read_inheritance_markdown_dir_with_multiple_leveraged_components(tmp_tr
assert len(inheritance_info[0]) == 2
assert len(inheritance_info[1]) == 2

assert 'ac-2_smt.a' in markdown_dict
assert len(markdown_dict['ac-2_smt.a']) == 2

assert expected_appliance_uuid in markdown_dict['ac-2_smt.a']
inheritance_info = markdown_dict['ac-2_smt.a'][expected_appliance_uuid]

# Only leveraging from one component
assert len(inheritance_info[0]) == 1
assert len(inheritance_info[1]) == 1


def test_update_type_with_by_comp(sample_implemented_requirement: ossp.ImplementedRequirement) -> None:
"""Test update type with by component."""
Expand Down Expand Up @@ -226,3 +251,13 @@ def test_update_type_with_by_comp(sample_implemented_requirement: ossp.Implement
assert new_by_comp.component_uuid == test_comp_uuid
assert new_by_comp.satisfied is not None
assert new_by_comp.satisfied[0].description == 'Updated Description'

# Test removing the existing inheritance info
test_by_comp_dict: exportreader.ByComponentDict = {}
reader._update_type_with_by_comp(sample_implemented_requirement, test_by_comp_dict)

new_by_comp = sample_implemented_requirement.by_components[1] # type: ignore

assert new_by_comp.component_uuid == test_comp_uuid
assert new_by_comp.satisfied is None
assert new_by_comp.inherited is None
26 changes: 15 additions & 11 deletions trestle/core/crm/export_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ def read_exports_from_markdown(self) -> ossp.SystemSecurityPlan:

# Process remaining markdown information that was not in the implemented requirements
for control_id, by_comp_dict in markdown_dict.items():
logging.debug(f'Adding control mapping {control_id} to implemented requirements')
self._add_control_mappings_to_implemented_requirements(control_id, by_comp_dict)
if by_comp_dict:
logging.debug(f'Adding control mapping {control_id} to implemented requirements')
self._add_control_mappings_to_implemented_requirements(control_id, by_comp_dict)

self._ssp.control_implementation.implemented_requirements = list(self._implemented_requirements.values())
return self._ssp
Expand Down Expand Up @@ -124,17 +125,19 @@ def _update_type_with_by_comp(self, with_bycomp: TypeWithByComps, by_comp_dict:
by_comp: ossp.ByComponent
for by_comp in as_list(with_bycomp.by_components):

# If the by_component uuid exists in the by_comp_dict, then update it
# If not, clear the by_component inheritance information
comp_inheritance_info: Tuple[List[ossp.Inherited], List[ossp.Satisfied]] = ([], [])
if by_comp.component_uuid in by_comp_dict:
comp_inheritance_info = by_comp_dict[by_comp.component_uuid]

bycomp_interface = ByComponentInterface(by_comp)
by_comp = bycomp_interface.reconcile_inheritance_by_component(
comp_inheritance_info[0], comp_inheritance_info[1]
)

# Delete the entry from the by_comp_dict once processed to avoid duplicates
del by_comp_dict[by_comp.component_uuid]

bycomp_interface = ByComponentInterface(by_comp)
by_comp = bycomp_interface.reconcile_inheritance_by_component(
comp_inheritance_info[0], comp_inheritance_info[1]
)

new_by_comp.append(by_comp)

# Add any new by_components that were not in the original statement
Expand Down Expand Up @@ -224,7 +227,8 @@ def _read_inheritance_markdown_directory(self) -> InheritanceViewDict:
satisfied.append(leveraged_info.satisfied)

by_comp_dict[comp_uuid] = (inherited, satisfied)
# If there is information in the by_component dictionary, then update the markdown dictionary
if by_comp_dict:
markdown_dict[control_dir] = by_comp_dict

# Add the by_component dictionary to the markdown dictionary for the control directory
markdown_dict[control_dir] = by_comp_dict

return markdown_dict

0 comments on commit 6de26a1

Please sign in to comment.