# SPDX-FileCopyrightText: 2024 SPDX contributors
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: Apache-2.0
"""NTIA Minimum Elements checking functionality."""
from __future__ import annotations
import warnings
from .base_checker import BaseChecker
[docs]
class NTIAChecker(BaseChecker):
"""
NTIA Minimum Elements check.
See:
https://www.ntia.gov/report/2021/minimum-elements-software-bill-materials-sbom
"""
def __init__(
self,
file: str,
validate: bool = True,
compliance: str = "ntia",
sbom_spec: str = "spdx2",
):
"""
Initialize the NTIA Minimum Element Checker.
Args:
file (str): The name of the file to be checked.
validate (bool): Whether to validate the file.
compliance (str): The compliance standard to be used.
sbom_spec (str): The SBOM specification to be used.
"""
super().__init__(
file=file, validate=validate, compliance=compliance, sbom_spec=sbom_spec
)
if compliance not in {"ntia"}:
raise ValueError("Only NTIA Minimum Element compliance is supported.")
if self.doc:
self.compliant = self.check_compliance()
# for backward compatibility
self.ntia_minimum_elements_compliant = self.compliant
[docs]
def check_compliance(self) -> bool:
"""Check overall compliance with NTIA minimum elements."""
return all(
[
self.doc_author,
self.doc_timestamp,
self.dependency_relationships,
not self.components_without_names,
not self.components_without_versions,
not self.components_without_identifiers,
not self.components_without_suppliers,
not self.validation_messages,
]
)
[docs]
def check_ntia_minimum_elements_compliance(self) -> bool:
"""Check overall compliance with NTIA minimum elements.
This method is kept for backward compatibility.
Please consider using check_compliance() instead."""
warnings.warn(
"NTIAChecker.check_ntia_minimum_elements_compliance is deprecated; "
"use check_compliance() instead.",
DeprecationWarning,
stacklevel=2,
)
return self.check_compliance()
[docs]
def print_components_missing_info(self, attributes=None) -> None:
"""Print detailed info about which components have missing info."""
super().print_components_missing_info(
["name", "version", "identifier", "supplier"]
)
[docs]
def print_table_output(self, verbose: bool = False, table_elements=None) -> None:
"""Print element-by-element result table."""
super().print_table_output(
verbose=verbose,
table_elements=[
("All component names provided?", not self.components_without_names),
(
"All component versions provided?",
not self.components_without_versions,
),
(
"All component identifiers provided?",
not self.components_without_identifiers,
),
(
"All component suppliers provided?",
not self.components_without_suppliers,
),
("SBOM author name provided?", self.doc_author),
("SBOM creation timestamp provided?", self.doc_timestamp),
("Dependency relationships provided?", self.dependency_relationships),
],
)
[docs]
def output_html(self, table_elements=None) -> str:
"""Create a HTML of results."""
return super().output_html(
table_elements=[
("All component names provided", not self.components_without_names),
(
"All component versions provided",
not self.components_without_versions,
),
(
"All component identifiers provided",
not self.components_without_identifiers,
),
(
"All component suppliers provided",
not self.components_without_suppliers,
),
("SBOM author name provided", self.doc_author),
("SBOM creation timestamp provided", self.doc_timestamp),
("Dependency relationships provided", self.dependency_relationships),
],
)