警告

此功能是实验性的,可能会发生重大更改。 有关更多信息,请参阅Conan 稳定性部分。

conan.tools.sbom

软件物料清单 (SBOM) 是一种文档,其中列出了组成特定软件的所有组件、库、依赖项和其他元素。 类似于制造业中的物料清单,它详细说明了用于构建产品的零件和材料,SBOM 提供了关于应用程序或软件系统“内部”包含的内容的透明度。

Conan 允许您通过使用已解析的依赖关系图来原生生成 SBOM。 这样,您可以在构建程序的同时创建 SBOM。

目前,此功能处于实验状态,这意味着界面、功能或生成的文件将来可能会发生更改。 此外,它目前支持 CycloneDX 1.4 和 1.6 版本。 如果您需要不同的标准、其他版本,或者如果您遇到任何潜在的改进,请随时在我们的 GitHub 上提出问题。 我们很乐意听到您的反馈!

CycloneDX

Conan 开箱即用地支持 CycloneDX,它是 SBOM 最广泛使用的标准之一。

CycloneDX 工具位于 conan.tools.sbom.cyclonedx 模块中。 它提供了 cyclonedx_1_4cyclonedx_1_6 函数,它们接收一个 conanfile 并返回一个字典,其中包含 CycloneDX 1.4/1.6 JSON 格式的 SBOM 数据。

cyclonedx_1_4(conanfile, name=None, add_build=False, add_tests=False, **kwargs)

(实验性) 生成带有 JSON 格式的 cyclone 1.4 SBOM

从给定的依赖关系图创建 CycloneDX 1.4 软件物料清单 (SBOM)。

参数

conanfile:conanfile 实例。 name (str, optional):元数据字段的自定义名称。 add_build (bool, optional, default=False):包括构建依赖项。 add_tests (bool, optional, default=False):包括测试依赖项。

返回值

生成的 CycloneDX 1.4 文档作为字符串。

用法示例:` cyclonedx_1_4(conanfile, name="custom_name", add_build=True, add_test=True, **kwargs) `

cyclonedx_1_6(conanfile, name=None, add_build=False, add_tests=False, **kwargs)

(实验性) 生成带有 JSON 格式的 cyclone 1.6 SBOM

从给定的依赖关系图创建 CycloneDX 1.6 软件物料清单 (SBOM)。

参数

conanfile:conanfile 实例。 name (str, optional):元数据字段的自定义名称。 add_build (bool, optional, default=False):包括构建依赖项。 add_tests (bool, optional, default=False):包括测试依赖项。

返回值

生成的 CycloneDX 1.6 文档作为字符串。

用法示例:` cyclonedx_1_6(conanfile, name="custom_name", add_build=True, add_test=True, **kwargs) `

使用此功能就像在您的客户端中实现一个 hook,该 hook 使用此工具创建 SBOM 并将其存储在适当的位置一样简单。

用法示例

让我们看两个例子

在第一个示例中,我们希望在创建应用程序时(在 package 方法之后)生成 SBOM。 这对于跟踪构建软件所使用的组件和依赖项非常有用。 在示例中,我们将生成的 SBOM 保存在 package 元数据文件夹中,以保持项目的组织性

import json
import os
from conan.api.output import ConanOutput
from conan.tools.sbom.cyclonedx import cyclonedx_1_6

def post_package(conanfile, **kwargs):
    sbom_cyclonedx_1_6 = cyclonedx_1_6(conanfile)
    metadata_folder = conanfile.package_metadata_folder
    file_name = "sbom.cdx.json"
    with open(os.path.join(metadata_folder, file_name), 'w') as f:
        json.dump(sbom_cyclonedx_1_6, f, indent=4)
    ConanOutput().success(f"CYCLONEDX CREATED - {conanfile.package_metadata_folder}")

在第二个示例中,我们在 generate 方法之后生成 SBOM。 这允许我们在从 Conan 安装依赖项时创建 SBOM。 这对于为不同版本的依赖项生成 SBOM 非常有用。 请注意,这次我们将 SBOM 保存在 generators 文件夹中,以便安装依赖项的用户可以轻松访问 SBOM。

import json
import os
from conan.api.output import ConanOutput
from conan.tools.sbom.cyclonedx import cyclonedx_1_6

def post_generate(conanfile, **kwargs):
    sbom_cyclonedx_1_6 = cyclonedx_1_6(conanfile)
    generators_folder = conanfile.generators_folder
    file_name = "sbom.cdx.json"
    os.mkdir(os.path.join(generators_folder, "sbom"))
    with open(os.path.join(generators_folder, "sbom", file_name), 'w') as f:
        json.dump(sbom_cyclonedx_1_6, f, indent=4)
    ConanOutput().success(f"CYCLONEDX CREATED - {conanfile.generators_folder}")

这两个 hook 可以共存,这样我们可以分别生成应用程序和依赖项的 SBOM。 这可以极大地帮助我们对开发过程进行持续分析并确保软件质量。

生成基于 Conan 的 SBOM

我们可以采用“基于 Conan 的方法”而不是使用标准。 感谢 conanfile.subgraph.serialize() 函数,我们可以直接获取有关程序包依赖关系的信息。 在以下示例中,我们可以看到一个 hook,该 hook 生成一个简化的 SBOM,它由子图的序列化组成,其中包括 Conan 具有的关于特定依赖项的所有数据。 请注意,此序列化不是标准的 SBOM 格式,并且未以任何方式标准化。 该信息类似于 conan graph info ... --format=json 命令提供的信息。

import json
import os
from conan.api.output import ConanOutput

def post_package(conanfile, **kwargs):
    metadata_folder = conanfile.package_metadata_folder
    file_name = "sbom.conan.json"
    with open(os.path.join(metadata_folder, file_name), 'w') as f:
        json.dump(conanfile.subgraph.serialize(), f, indent=2)
    ConanOutput().success(f"CONAN SBOM CREATED - {conanfile.package_metadata_folder}")