Skip to content

Commit

Permalink
fix: assessment objectives formatting in markdown is not correct (#1414)
Browse files Browse the repository at this point in the history
* fix: assessment objectives formatting in markdown is not correct

Signed-off-by: Alejandro Jose Leiva Palomo <alejandro.leiva.palomo@ibm.com>

* fix: remove unneded variable

Signed-off-by: Alejandro Jose Leiva Palomo <alejandro.leiva.palomo@ibm.com>

---------

Signed-off-by: Alejandro Jose Leiva Palomo <alejandro.leiva.palomo@ibm.com>
  • Loading branch information
AleJo2995 authored Jun 30, 2023
1 parent e9dad2b commit dbfc1d6
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 3 deletions.
68 changes: 68 additions & 0 deletions tests/trestle/core/commands/author/profile_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from tests import test_utils

import trestle.common.const as const
import trestle.core.generators as gens
import trestle.oscal.catalog as cat
import trestle.oscal.common as com
import trestle.oscal.profile as prof
Expand Down Expand Up @@ -1115,3 +1116,70 @@ def test_profile_inherit(tmp_trestle_dir: pathlib.Path):
args.output = args.profile
prof_inherit = ProfileInherit()
assert prof_inherit._run(args) == 2


def test_profile_generate_assesment_objectives(tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch) -> None:
"""Test the profile markdown generator."""
_, _, _, _ = setup_profile_generate(tmp_trestle_dir, 'simple_test_profile.json')
yaml_header_path = test_utils.YAML_TEST_DATA_PATH / 'good_simple.yaml'

profile, _ = ModelUtils.load_model_for_class(tmp_trestle_dir, 'my_prof', prof.Profile, FileContentType.JSON)

# create with-id to load at-2 control with its corresponding assesment objectives
with_id_at_2 = gens.generate_sample_model(prof.WithId)
with_id_at_2.__root__ = 'at-2'

profile.imports[0].include_controls[0].with_ids.append(with_id_at_2)

ModelUtils.save_top_level_model(profile, tmp_trestle_dir, 'my_prof', FileContentType.JSON)

nist_cat, _ = ModelUtils.load_model_for_class(tmp_trestle_dir, 'nist_cat', cat.Catalog, FileContentType.JSON)
# create assesment objectives json for adding it to the control in the catalog
assesment_objectives = {
'id': 'at-2_obj',
'name': 'assessment-objective',
'props': [{
'name': 'label', 'value': 'AT-02', 'class': 'sp800-53a'
}],
'parts': [
{
'id': 'at-2_obj.a',
'name': 'assessment-objective',
'props': [{
'name': 'label', 'value': 'AT-02a.', 'class': 'sp800-53a'
}],
'parts': [
{
'id': 'at-2_obj.a.1-2',
'name': 'assessment-objective',
'props': [{
'name': 'label', 'value': 'AT-02a.01[02]', 'class': 'sp800-53a'
}],
'prose': 'some example prose'
},
{
'id': 'at-2_obj.a.1-3',
'name': 'assessment-objective',
'props': [{
'name': 'label', 'value': 'AT-02a.01[03]', 'class': 'sp800-53a'
}],
'prose': 'some example prose'
}
]
}
]
}

at_2 = nist_cat.groups[1].controls[1]
at_2.parts.append(assesment_objectives)
ModelUtils.save_top_level_model(nist_cat, tmp_trestle_dir, 'nist_cat', FileContentType.JSON)

# convert resolved profile catalog to markdown then assemble it after adding an item to a control
# generate, edit, assemble
test_args = f'trestle author profile-generate -n {prof_name} -o {md_name} -rs NeededExtra'.split( # noqa E501
)
test_args.extend(['-y', str(yaml_header_path)])
test_args.extend(['-s', all_sections_str])
monkeypatch.setattr(sys, 'argv', test_args)

assert Trestle().run() == 0
1 change: 1 addition & 0 deletions trestle/common/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@
TEMPLATE_VERSION_REGEX = r'[0-9]+.[0-9]+.[0-9]+'

OBJECTIVE_PART = 'objective'
ASSESMENT_OBJECTIVE_PART = 'assessment-objective'
TABLE_OF_PARAMS_PART = 'table_of_parameters'

# extracts standalone uuid's from anywhere in string
Expand Down
8 changes: 5 additions & 3 deletions trestle/core/control_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,20 @@ def _add_control_statement(self, control: cat.Control, group_title: str, print_g
def _add_control_objective(self, control: cat.Control) -> None:
if control.parts:
for part in control.parts:
if part.name == 'objective':
if part.name == const.OBJECTIVE_PART or part.name == const.ASSESMENT_OBJECTIVE_PART:
self._md_file.new_paragraph()
heading_title = 'Control Objective'
if part.name == const.ASSESMENT_OBJECTIVE_PART:
heading_title = 'Control Assessment Objective'
self._md_file.new_header(level=2, title=heading_title)
self._md_file.set_indent_level(-1)
self._add_part_and_its_items(control, 'objective', 'objective')
self._add_part_and_its_items(control, part.name, part.name)
self._md_file.set_indent_level(-1)
return

def _add_sections(self, control: cat.Control, allowed_sections: Optional[List[str]]) -> None:
"""Add the extra control sections after the main ones."""
skip_section_list = [const.STATEMENT, const.ITEM, const.OBJECTIVE_PART]
skip_section_list = [const.STATEMENT, const.ITEM, const.OBJECTIVE_PART, const.ASSESMENT_OBJECTIVE_PART]
while True:
_, name, title, prose = ControlInterface.get_section(control, skip_section_list)
if not name:
Expand Down

0 comments on commit dbfc1d6

Please sign in to comment.