protobom/protobom

GitHub: protobom/protobom

protobom 是一个使用 Protocol Buffers 的通用 SBOM 工具,解决不同SBOM格式间的无损转换和编程操作问题。

Stars: 324 | Forks: 58

Protobom Logo

# protobom 文档 OpenSSF Sandbox Badge `protobom` 是 SBOM 数据的一种 [Protocol Buffers](https://protobuf.dev/getting-started/) 表示形式,能够无损地摄取现代 [SPDX](https://spdx.dev/) 和 [CycloneDX](https://cyclonedx.org/) 版本的文档。它包含一个从 protocol buffers 定义生成的配套 Go 库,该库也实现了这些格式的摄取器。 标准 SBOM 由读取器通过使用理解常见格式的[反序列化器](docs/unserializers.md)来读取。反序列化器从读取的 CycloneDX 或 SPDX 文档数据创建一个中立的 protobom。 protobom 可以由写入器使用知道如何生成这些文档的[序列化器](docs/serializers.md)渲染成标准 SBOM 格式。 ## 支持的版本和格式 下表总结了当前 Go 语言库中支持的格式和编码。 | 格式 | 版本 | 编码 | 读取 | 写入 | | --- | --- | --- | --- | --- | | SPDX | 2.2 | JSON | 计划中 | - | | SPDX | 2.2 | tag-value | 计划中 | - | | SPDX | 2.3 | JSON | 支持 | 支持 | | SPDX | 2.3 | tag-value | 计划中 | - | | SPDX | 3.0 | JSON | 计划中 | 计划中 | | CycloneDX | 1.4 | JSON | 支持 | 支持 | | CycloneDX | 1.5 | JSON | 支持 | 支持 | | CycloneDX | 1.6 | JSON | 支持 | 支持 | 其他读取和写入实现可能可以用[protobuf 支持的其他语言](https://protobuf.dev/getting-started/)编写。 ## 用法 `protobom` 库可用于读取和写入上述任何格式的 SBOM 文档。 ### 示例 1:sbom-convert 项目 https://github.com/protobom/sbom-convert 提供了一个使用该库将 SBOM 摄取到 protobom 中间格式,然后以不同格式写入新 SBOM 文档的完整示例。 ### 示例 2:读入 SBOM 文档以操作特定字段 `protobom` 库是使用 Go 编程语言与 SBOM 文档交互的最佳且最简单的方式。在此示例中,我们展示了如何通过创建一个新的 protobom `Reader` 并调用 `reader.ParseFile()` 来读取 SBOM 文档文件并返回一个 protobom sbom.Document,从而轻松地以编程方式访问 SBOM。在此示例中,无论格式如何,protobom 都会处理文档的反序列化。然后,使用 protobom 的开发者可以操作一个一致的 protobom 中间表示,而实际的文件格式被抽象化。 此特定示例遍历 SBOM 文档节点列表中的每个节点,并打印每个节点的 ID、Name 和 Version。如果输入文档是 SPDX SBOM,每个 protobom Node 将描述一个 SPDX 包。如果输入文档是 CycloneDX SBOM,每个 protobom Node 将描述一个 CycloneDX 组件。使用 protobom 的开发者无需根据输入格式更改代码。protobom 库解析输入文档以呈现数据的中间格式,允许开发者操作一致的中间格式。 ``` package main import ( "fmt" "github.com/protobom/protobom/pkg/reader" ) func main() { // Create a new protobom SBOM reader: reader := reader.New() document, err := reader.ParseFile("sbom.spdx.json") if err != nil { fmt.Printf("ERROR: %v\n", err) return } // List all nodes in the SBOM and print some information about them: for _, node := range document.GetNodeList().GetNodes() { fmt.Printf("Node ID [%v]: name: %v version: %v\n", node.GetId(), node.GetName(), node.GetVersion()) } } ``` ### 示例 3:以编程方式生成 SBOM 文档 开发者可以使用 `protobom` 库基于单独的 SBOM 文档内容生成 SBOM 文档,正如 [sbom-convert](https://github.com/protobom/sbom-convert) 项目所示。 然而,`protobom` 中间表示也可用于创建新的 SBOM 文档。开发者可以创建一个新的 `protobom` 文档,并使用 Go 编程语言填充 SBOM 文档所需的字段。然后,开发者将创建一个新的 Writer 来定义 SBOM 应写入的位置以及应将 SBOM 写入的格式,并传入以编程方式定义的 SBOM 结构。protobom v0.2.0 版本包含六个为 Writer.New() 注册的序列化格式:SPDX23JSON、CDX12JSON、CDX13JSON、CDX14JSON、CDX15JSON 和 CDX16JSON。 ``` package main import ( "os" "github.com/protobom/protobom/pkg/formats" "github.com/protobom/protobom/pkg/sbom" "github.com/protobom/protobom/pkg/writer" ) func main() { // Create a new protobom document document := sbom.NewDocument() // Populate some of the document metadata: // ...for example the author: document.Metadata.Authors = append( document.Metadata.Authors, &sbom.Person{Name: "John Doe"}, ) // ...and the tool that produced the SBOM: document.Metadata.Tools = append( document.Metadata.Tools, &sbom.Tool{ Name: "ACME SBOM Tool", Version: "1.0", Vendor: "ACME Corporation"}, ) // Create a node to represent the application: appNode := &sbom.Node{ Id: "pkg:generic/my-software@v1.0.0", PrimaryPurpose: []sbom.Purpose{sbom.Purpose_APPLICATION}, Name: "My Software Name", Version: "v1.0.0", Licenses: []string{"Apache-2.0"}, LicenseConcluded: "Apache-2.0", LicenseComments: "Apache License", } // Add the application node to the document's nodelist: document.NodeList.AddRootNode(appNode) // Create two nodes to describe files in the application node1 := &sbom.Node{ Id: "File--usr-lib-libsoftware.so", Type: sbom.Node_FILE, Name: "/usr/lib/libsoftware.so", Version: "1", Copyright: "Copyright 2023 The ACME Corporation", Description: "Software Lib", } node1.AddHash(sbom.HashAlgorithm_SHA1, "f3ae11065cafc14e27a1410ae8be28e600bb8336") node1.AddHash(sbom.HashAlgorithm_SHA256, "4f232eeb99e1663d07f0af1af6ea262bf594934b694228e71fd8f159f9a19f32") node1.AddHash(sbom.HashAlgorithm_SHA512, "8044d0df34242699ad73bfe99b9ac3d6bbdaa4f8ebce1e23ee5c7f9fe59db8ad7b01fe94e886941793aee802008a35b05a30bc51426db796aa21e5e91b7ed9be") document.NodeList.AddNode(node1) node2 := &sbom.Node{ Id: "File--usr-bin-software", Type: sbom.Node_FILE, Name: "/usr/bin/software", Version: "1.0", Copyright: "Copyright 2023 The ACME Corporation", Description: "Software binary", } node2.AddHash(sbom.HashAlgorithm_SHA1, "defee82004d22fc92ab81c0c952a62a2172bda8c") node2.AddHash(sbom.HashAlgorithm_SHA256, "ad291c9572af8fc2ec8fd78d295adf7132c60ad3d10488fb63d120fc967a4132") node2.AddHash(sbom.HashAlgorithm_SHA512, "5940d8647907831e77ec00d81b318ca06655dbb0fd36d112684b03947412f0f98ea85b32548bc0877f3d7ce8f4de9b2c964062df44742b98c8e9bd851faecce9") // Relate the application package and the files. This adds the nodes to // the document graph: document.NodeList.RelateNodeAtID(node1, appNode.Id, sbom.Edge_contains) document.NodeList.RelateNodeAtID(node2, appNode.Id, sbom.Edge_contains) // Now render the document to STDOUT: w := writer.New() // Write the SBOM to STDOUT in SPDX 2.3: w.WriteStreamWithOptions( document, os.Stdout, &writer.Options{Format: formats.SPDX23JSON}, ) // Write the SBOM to STDOUT in CycloneDX 1.4: w.WriteStreamWithOptions( document, os.Stdout, &writer.Options{Format: formats.CDX14JSON}, ) } ``` ## 加入 Protobom 社区! - 来 [OpenSSF Slack 的 `#protobom`](https://openssf.slack.com/archives/C06ED97EQ4B) 频道打招呼。 - [Protobom 社区会议](https://zoom-lfx.platform.linuxfoundation.org/meeting/93849959680?password=414218a0-8865-4cea-ba62-99443815ceff&invite=true) - 每隔一周太平洋时间上午 9 点。 - [OpenSSF 安全工具工作组会议](https://zoom-lfx.platform.linuxfoundation.org/meeting/94897563315?password=7f03d8e7-7bc9-454e-95bd-6e1e09cb3b0b) - 每隔一周太平洋时间上午 8 点。
标签:CycloneDX, EVTX分析, Go 语言, ingesters, JSON, OpenSSF, Protocol Buffers, SBOM, SBOM 管理, serializers, SPDX, unserializers, 二进制发布, 开源工具, 数据表示, 数据读写, 日志审计, 格式转换, 硬件无关, 跌倒检测, 软件物料清单, 软件透明度