Skip to content

Commit

Permalink
feat: CPLYTM-421 create validation component from rules
Browse files Browse the repository at this point in the history
Signed-off-by: Sophia Wang <huiwang@redhat.com>
  • Loading branch information
huiwangredhat committed Jan 14, 2025
1 parent caaa44d commit e598832
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
2 changes: 1 addition & 1 deletion trestlebot/cli/commands/sync_cac_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
)
@click.option(
"--component-definition-type",
type=click.Choice(["service", "validation"]),
type=click.Choice(["service", "validation", "software"]),
help="Type of component definition. Default: service",
required=False,
default="service",
Expand Down
29 changes: 24 additions & 5 deletions trestlebot/tasks/sync_cac_content_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
RuleInfo,
RulesTransformer,
get_component_info,
get_validation_component_mapping,
)


Expand Down Expand Up @@ -84,25 +85,43 @@ def _create_or_update_compdef(self, compdef_type: str = "service") -> None:
product_name, full_name = get_component_info(
self.product, self.cac_content_root
)
oscal_component.title = product_name
oscal_component.type = compdef_type
oscal_component.description = full_name
all_rule_properties = self._get_rules_properties()
oscal_component.props = none_if_empty(all_rule_properties)

props = none_if_empty(all_rule_properties)
oscal_component.type = self.compdef_type
if oscal_component.type == "validation":
oscal_component.title = "openscap"
oscal_component.description = "openscap"
oscal_component.props = get_validation_component_mapping(props)
else:
oscal_component.title = product_name
oscal_component.description = full_name
oscal_component.props = props
repo_path = pathlib.Path(self.working_dir)
cd_dir = repo_path.joinpath(f"{trestle_const.MODEL_DIR_COMPDEF}/{self.product}")
cd_json = cd_dir / "component-definition.json"
if cd_json.exists():
logger.info(f"The component definition for {self.product} exists.")
compdef = ComponentDefinition.oscal_read(cd_json)
components_titles = []
updated = False
for index, component in enumerate(compdef.components):
components_titles.append(component.title)
# If the component exists and the props need to be updated
if component.title == oscal_component.title:
if component.props != oscal_component.props:
logger.info(
f"Start to update the props of the component {component.title}"
)
compdef.components[index].props = oscal_component.props
updated = True
compdef.oscal_write(cd_json)
break
# If the component doesn't exist, append this component
if oscal_component.title not in components_titles:
logger.info(f"Start to append the component {oscal_component.title}")
compdef.components.append(oscal_component)
compdef.oscal_write(cd_json)
updated = True
if updated:
logger.info(f"Update component definition: {cd_json}")
compdef.metadata.version = str(
Expand Down
39 changes: 39 additions & 0 deletions trestlebot/transformers/cac_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,45 @@ def get_component_info(product_name: str, cac_path: str) -> Tuple[str, str]:
raise ValueError("component_title is empty or None")


def get_validation_component_mapping(
props: List[Dict[str, str]]
) -> List[Dict[str, str]]:
"""
Adds a new "Check_Id" and "Check_Description" to the props based on the
"Rule_Id" value and "Rule_Description".
Args:
props (List[Dict]): The input list of dictionaries.
Returns:
List[Dict]: The updated list with the new "Check_Id" and
"Check_Description" entry.
"""
props = props
rule_check_mapping = []
check_id_entry = {}
for prop in props:
if prop["name"] == "Rule_Id":
rule_check_mapping.append(prop)
check_id_entry = {
"name": "Check_Id",
"ns": prop["ns"],
"value": prop["value"],
"remarks": prop["remarks"],
}
if prop["name"] == "Rule_Description":
rule_check_mapping.append(prop)
rule_check_mapping.append(check_id_entry)
check_description_entry = {
"name": "Check_Description",
"ns": prop["ns"],
"value": prop["value"],
"remarks": prop["remarks"],
}
rule_check_mapping.append(check_description_entry)
return rule_check_mapping


def add_prop(name: str, value: str, remarks: Optional[str] = None) -> Property:
"""Add a property to a set of rule properties."""
prop = generate_sample_model(Property)
Expand Down

0 comments on commit e598832

Please sign in to comment.