Skip to content

Commit

Permalink
test: adds integration test bewtween rules transform, assemble, and r…
Browse files Browse the repository at this point in the history
…egenerate

Fixes bug in component definition autosync
Update AuthoredComponentsDefinition to AuthoredComponentDefinition

Signed-off-by: Jennifer Power <[email protected]>
  • Loading branch information
jpower432 committed Oct 16, 2023
1 parent b4998f4 commit f514b3a
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 13 deletions.
16 changes: 16 additions & 0 deletions tests/integration/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/python

# Copyright 2023 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Integration tests between different types of tasks classes."""
117 changes: 117 additions & 0 deletions tests/integration/test_rules_transform_workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/usr/bin/python

# Copyright 2023 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""Component test the rules transformation workflow."""

import os
import pathlib

from trestle.common.load_validate import load_validate_model_name
from trestle.oscal import component as comp

import trestlebot.const as const
from tests.testutils import setup_for_profile
from trestlebot.tasks.assemble_task import AssembleTask
from trestlebot.tasks.authored.compdef import AuthoredComponentDefinition
from trestlebot.tasks.authored.types import AuthoredType
from trestlebot.tasks.regenerate_task import RegenerateTask
from trestlebot.tasks.rule_transform_task import RuleTransformTask
from trestlebot.transformers.yaml_transformer import ToRulesYAMLTransformer


test_component_definition = "test_component_definition"
test_profile = "simplified_nist_profile"
test_md_path = "md_compdef"


def test_rules_transform_workflow(tmp_trestle_dir: str) -> None:
"""Test the rules transformation workflow for component definitions."""

trestle_root_path = pathlib.Path(tmp_trestle_dir)

# Environment setup and initial rule generation
_ = setup_for_profile(trestle_root_path, test_profile, test_profile)

authored_compdef = AuthoredComponentDefinition(trestle_root=tmp_trestle_dir)
authored_compdef.create_new_default(
profile_name=test_profile,
compdef_name=test_component_definition,
comp_title="Test",
comp_description="Test component definition",
comp_type="service",
)

# Transform
transform = RuleTransformTask(
tmp_trestle_dir, const.RULES_VIEW_DIR, ToRulesYAMLTransformer()
)
transform.execute()

# Load the component definition
compdef: comp.ComponentDefinition
compdef, _ = load_validate_model_name(
trestle_root_path, test_component_definition, comp.ComponentDefinition
)

assert len(compdef.components) == 1
component = compdef.components[0]

assert component.title == "Test"
assert component.description == "Test component definition"
assert component.type == "service"
assert len(component.props) == 24
assert len(component.control_implementations) == 1
assert (
component.control_implementations[0].source
== f"trestle://profiles/{test_profile}/profile.json"
)

last_modified = compdef.metadata.last_modified

# Run regenerate
regenerate = RegenerateTask(
tmp_trestle_dir, AuthoredType.COMPDEF.value, test_md_path
)
regenerate.execute()

assert os.path.exists(
os.path.join(trestle_root_path, test_md_path, test_component_definition)
)

# Run assemble
assemble = AssembleTask(tmp_trestle_dir, AuthoredType.COMPDEF.value, test_md_path)
assemble.execute()

# Load the component definition
compdef, _ = load_validate_model_name(
trestle_root_path, test_component_definition, comp.ComponentDefinition
)

assert len(compdef.components) == 1
component = compdef.components[0]

# Asset last modified is updated, but all expected information is still present
assert compdef.metadata.last_modified > last_modified

assert component.title == "Test"
assert component.description == "Test component definition"
assert component.type == "service"
assert len(component.props) == 24
assert len(component.control_implementations) == 1
assert (
component.control_implementations[0].source
== f"trestle://profiles/{test_profile}/profile.json"
)
10 changes: 6 additions & 4 deletions tests/trestlebot/tasks/authored/test_compdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from tests import testutils
from trestlebot.const import RULES_VIEW_DIR, YAML_EXTENSION
from trestlebot.tasks.authored.base_authored import AuthoredObjectException
from trestlebot.tasks.authored.compdef import AuthoredComponentsDefinition
from trestlebot.tasks.authored.compdef import AuthoredComponentDefinition
from trestlebot.transformers.yaml_transformer import ToRulesYAMLTransformer


Expand All @@ -37,7 +37,7 @@ def test_create_new_default(tmp_trestle_dir: str) -> None:
# Prepare the workspace
trestle_root = pathlib.Path(tmp_trestle_dir)
_ = testutils.setup_for_profile(trestle_root, test_prof, "")
authored_comp = AuthoredComponentsDefinition(tmp_trestle_dir)
authored_comp = AuthoredComponentDefinition(tmp_trestle_dir)

authored_comp.create_new_default(test_prof, test_comp, "test", "My desc", "service")

Expand Down Expand Up @@ -75,7 +75,9 @@ def test_create_new_default(tmp_trestle_dir: str) -> None:
"NIST Special Publication 800-53 Revision 5 MODERATE IMPACT \
BASELINE"
)
assert rule.profile.href == "profiles/simplified_nist_profile/profile.json"
assert (
rule.profile.href == "trestle://profiles/simplified_nist_profile/profile.json"
)
assert rule.profile.include_controls is not None
assert len(rule.profile.include_controls) == 1
assert rule.profile.include_controls[0].id == "ac-5"
Expand All @@ -87,7 +89,7 @@ def test_create_new_default_no_profile(tmp_trestle_dir: str) -> None:
trestle_root = pathlib.Path(tmp_trestle_dir)
_ = testutils.setup_for_compdef(trestle_root, test_comp, "")

authored_comp = AuthoredComponentsDefinition(tmp_trestle_dir)
authored_comp = AuthoredComponentDefinition(tmp_trestle_dir)

with pytest.raises(
AuthoredObjectException, match="Profile fake does not exist in the workspace"
Expand Down
4 changes: 2 additions & 2 deletions tests/trestlebot/tasks/authored/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
AuthorObjectBase,
)
from trestlebot.tasks.authored.catalog import AuthoredCatalog
from trestlebot.tasks.authored.compdef import AuthoredComponentsDefinition
from trestlebot.tasks.authored.compdef import AuthoredComponentDefinition
from trestlebot.tasks.authored.profile import AuthoredProfile
from trestlebot.tasks.authored.ssp import AuthoredSSP

Expand Down Expand Up @@ -69,7 +69,7 @@ def test_get_authored_compdef(tmp_trestle_dir: str) -> None:
)

assert authored_object.get_trestle_root() == tmp_trestle_dir
assert isinstance(authored_object, AuthoredComponentsDefinition)
assert isinstance(authored_object, AuthoredComponentDefinition)


def test_get_authored_ssp(tmp_trestle_dir: str) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def test_profile_regenerate_task(tmp_trestle_dir: str) -> None:
def test_compdef_regenerate_task(tmp_trestle_dir: str) -> None:
"""Test compdef regenerate at the task level"""
trestle_root = pathlib.Path(tmp_trestle_dir)
md_path = os.path.join(compdef_md_dir, test_comp)
md_path = os.path.join(compdef_md_dir, test_comp, test_comp)
_ = testutils.setup_for_compdef(trestle_root, test_comp, md_path)

regenerate_task = RegenerateTask(
Expand Down
10 changes: 6 additions & 4 deletions trestlebot/tasks/authored/compdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import pathlib
from typing import List

import trestle.common.const as const
import trestle.oscal.profile as prof
from trestle.common.err import TrestleError
from trestle.common.model_utils import ModelUtils
Expand All @@ -41,7 +42,7 @@
from trestlebot.transformers.yaml_transformer import FromRulesYAMLTransformer


class AuthoredComponentsDefinition(AuthorObjectBase):
class AuthoredComponentDefinition(AuthorObjectBase):
"""
Class for authoring OSCAL Component Definitions in automation
"""
Expand All @@ -62,7 +63,7 @@ def assemble(self, markdown_path: str, version_tag: str = "") -> None:
success = authoring.assemble_component_definition_markdown(
name=compdef,
output=compdef,
markdown_dir=os.path.join(markdown_path, compdef),
markdown_dir=markdown_path,
regenerate=False,
version=version_tag,
)
Expand All @@ -83,7 +84,7 @@ def regenerate(self, model_path: str, markdown_path: str) -> None:
try:
success = authoring.generate_component_definition_markdown(
name=comp_name,
output=markdown_path,
output=os.path.join(markdown_path, comp_name),
force_overwrite=False,
)
if not success:
Expand Down Expand Up @@ -165,7 +166,8 @@ def add_rules_for_profile(
name=f"rule-{control_id}",
description=f"Rule for {control_id}",
profile=Profile(
href=str(profile_path.relative_to(self._trestle_root)),
href=const.TRESTLE_HREF_HEADING
+ str(profile_path.relative_to(self._trestle_root)),
description=catalog.metadata.title,
include_controls=[Control(id=control_id)],
),
Expand Down
4 changes: 2 additions & 2 deletions trestlebot/tasks/authored/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
AuthorObjectBase,
)
from trestlebot.tasks.authored.catalog import AuthoredCatalog
from trestlebot.tasks.authored.compdef import AuthoredComponentsDefinition
from trestlebot.tasks.authored.compdef import AuthoredComponentDefinition
from trestlebot.tasks.authored.profile import AuthoredProfile
from trestlebot.tasks.authored.ssp import AuthoredSSP, SSPIndex

Expand All @@ -48,7 +48,7 @@ def get_authored_object(
elif input_type == AuthoredType.PROFILE.value:
return AuthoredProfile(working_dir)
elif input_type == AuthoredType.COMPDEF.value:
return AuthoredComponentsDefinition(working_dir)
return AuthoredComponentDefinition(working_dir)
elif input_type == AuthoredType.SSP.value:
ssp_index: SSPIndex = SSPIndex(ssp_index_path)
return AuthoredSSP(working_dir, ssp_index)
Expand Down

0 comments on commit f514b3a

Please sign in to comment.