生成 CycloneDX BOM
SBOM(软件物料清单)是一个清单,用于描述给定软件分发版包含哪些组件。此外,它还可以包含更多信息,例如组件之间的关系、许可证、来源等。SBOM 通常由软件安全和软件供应链风险管理工具使用,以执行与漏洞和合规性相关的分析。
本指南使用 CycloneDX 规范描述 Quarkus 的 SBOM 生成功能。
为什么需要 Quarkus 特定的工具?
虽然 Quarkus 集成了 Maven 和 Gradle 等构建工具,但它本身也可以被归类为一种构建工具,拥有自己的组件和依赖模型、构建步骤和构建结果。Quarkus 应用程序的一个重要组件类型是 Quarkus 扩展,它包含运行时和构建时工件及其依赖项。
为了正确解析 Quarkus 扩展和其他应用程序依赖项,Quarkus 使用自己的依赖解析器,该解析器构建在底层构建工具(Maven 或 Gradle)提供的依赖解析器之上。
因此,以 Maven 为例,dependency:tree
的结果将不包括 Quarkus 用于构建应用程序的所有依赖项。类似的问题也会影响其他依赖分析工具,这些工具假定项目遵循标准的 Maven 依赖模型:它们将无法捕获有效的 Quarkus 应用程序依赖图。不幸的是,这包括 CycloneDX Maven 插件的实现。
除了作为构建过程输入的依赖项之外,构建的结果是应用程序的最终分发版。应用程序的用户可能会要求一个 SBOM,它不仅清单依赖项(构建的输入),还清单最终分发版(构建的输出),然后再同意部署应用程序。Quarkus 允许应用程序开发人员为他们的应用程序选择各种打包类型,其中一些是 Quarkus 特有的。提供关于包含在分发版中的组件的某些 Quarkus 特定详细信息,可能有助于更好地评估潜在安全相关问题的受影响程度。
依赖项 SBOM
本章介绍如何生成仅清单应用程序构建之前的依赖项的 SBOM。换句话说,这些 SBOM 将清单构建的输入。这些 SBOM 可用于在构建应用程序之前执行与漏洞和合规性相关的分析。
Maven 依赖项 SBOM
对于 Quarkus Maven 项目,可以使用 quarkus:dependency-sbom
目标来生成依赖项 SBOM。该目标的输出将保存在 target/<artifactId>-<version>-dependency-cyclonedx.json
文件中(可以通过设置 outputFile
目标参数或 quarkus.dependency.sbom.output-file
属性来更改)。完整的 Quarkus 构建和运行时依赖关系图将以 CycloneDX JSON
格式记录。
可以通过将 format
目标参数(或 quarkus.dependency.sbom.format
属性)设置为 xml
来请求 XML
格式。
生成的 SBOM 中的每个组件将包含 quarkus:component:scope
属性,该属性指示该组件是仅在运行时使用,还是在开发/构建时使用。
{
"name" : "quarkus:component:scope",
"value" : "runtime"
}
默认情况下,quarkus:dependency-sbom
会捕获生产构建的依赖项。Quarkus 支持三种应用程序引导模式:正常(生产)、测试和开发。在这三种模式下,应用程序可能具有不同的依赖关系图。mode
参数可用于指示应记录哪个依赖关系图。如果 mode
设置为 test
或 dev
,则目标文件名将变为 target/<artifactId>-<version>-<mode>-dependency-cyclonedx.json
。
可以通过执行 mvn help:describe -Dcmd=quarkus:dependency-sbom -Ddetail
来获取完整的参数集及其说明。
Gradle 依赖项 SBOM
与 Maven 不同,Gradle CycloneDX 插件实现可以在 Quarkus 项目中使用,以生成依赖项 SBOM,因为该实现清单了已配置插件注册的依赖项配置。
请参考 Gradle CycloneDX 插件文档以了解其配置选项。以下是与清单相关的 Quarkus 依赖项配置列表:
-
quarkusProdRuntimeClasspathConfiguration
- Quarkus 应用程序生产运行时依赖项; -
quarkusProdRuntimeClasspathConfigurationDeployment
- Quarkus 应用程序生产运行时和构建时依赖项; -
quarkusTestRuntimeClasspathConfiguration
- Quarkus 应用程序测试运行时依赖项; -
quarkusTestRuntimeClasspathConfigurationDeployment
- Quarkus 应用程序测试运行时和构建时依赖项; -
quarkusDevRuntimeClasspathConfiguration
- Quarkus 应用程序开发模式运行时依赖项; -
quarkusDevRuntimeClasspathConfigurationDeployment
- Quarkus 应用程序开发模式运行时和构建时依赖项。
鉴于该插件不知道 Quarkus 如何使用这些依赖项,它将无法为组件设置 quarkus:component:scope
属性。另一方面,可以使用请求的配置名称来指示要定位的范围。
分发版 SBOM
本章介绍清单 Quarkus 构建结果(即最终应用程序分发版)的 SBOM。
在应用程序构建和打包过程中,Quarkus 会捕获有关生成的发行版的某些详细信息,然后允许 SBOM 生成器使用并以 SBOM 格式记录该信息。
目前,Quarkus 用户可用的唯一能够清单应用程序分发版的 SBOM 生成器是 io.quarkus:quarkus-cyclonedx
。一旦将其添加为项目依赖项,它将在每次构建应用程序时生成 SBOM。SBOM 将保存在项目构建输出目录中,文件名格式为 <executable-name>-cyclonedx.<format>
,其中:
-
<executable-name>
是启动应用程序的可执行文件的基本文件名(不带扩展名); -
<format>
是json
(默认)或xml
,可以通过quarkus.cyclonedx.format
属性进行配置。如果需要这两种格式,可以将quarkus.cyclonedx.format
设置为all
。
快速 JAR
快速 JAR 打包使用 Quarkus 特有的文件系统目录布局,其中包含 Quarkus 生成的文件以及应用程序运行时依赖的 Maven 构件。
快速 JAR 打包类型的 SBOM 将使用可执行 JAR 文件作为其主组件,并记录应用程序的运行时和构建时 Quarkus 依赖项。
运行时组件
快速 JAR 发行版中的每个文件将在 SBOM 中显示,其 quarkus:component:scope
属性设置为 runtime
,并且 evidence.occurrences.location
字段指向组件在应用程序发行版目录中的位置,例如:
"purl" : "pkg:maven/org.jboss.slf4j/slf4j-jboss-logmanager@2.0.0.Final?type=jar",
"properties" : [
{
"name" : "quarkus:component:scope",
"value" : "runtime"
}
],
"evidence" : {
"occurrences" : [
{
"location" : "lib/main/org.jboss.slf4j.slf4j-jboss-logmanager-2.0.0.Final.jar"
}
]
}
evidence.occurrences.location 在 CycloneDX 模式版本 1.5 中引入,对于旧版本,位置将使用 quarkus:component:location 属性指示。 |
血统
血统是一种提供信息的方式,表明某些补丁或更改已应用于某个组件。
在某些情况下,Quarkus 可能会将修改后的依赖项构件副本复制到应用程序发行版中。修改组件的原始内容会更改其哈希值,这可能会被比较原始组件哈希值与发行版中找到的值的工具标记为可疑。
当 Quarkus 应用从 Maven 存储库解析的构件的修改时,它可以将这些更改作为血统注释呈现在生成的 SBOM 中。例如,如果应用程序开发人员决定从依赖项中删除某些类路径资源,例如:
quarkus.class-loading.removed-resources."jakarta.transaction\:jakarta.transaction-api"=META-INF/NOTICE.md,jakarta/transaction/package.html
生成的 SBOM 将包含:
"purl" : "pkg:maven/jakarta.transaction/jakarta.transaction-api@2.0.1?type=jar",
"pedigree" : {
"notes" : "Removed META-INF/NOTICE.md,jakarta/transaction/package.html"
},
Uber JAR
Uber JAR 的 SBOM 将使用 Uber JAR Maven 构件作为其主组件。
由于 Uber JAR 本身作为 Maven 构件发布,因此为 Uber JAR 生成的 SBOM 也将自动作为 Maven 构件发布。但是,这可以通过将 quarkus:build
目标的 attachSboms
参数设置为 false
来禁用。
Gradle 用户必须显式配置发布插件才能将 SBOM 作为 Maven 构件部署。
Uber JAR 的 SBOM 中生成的运行时组件不包含 evidence.occurrences.location
,因为它们的内容合并到一个 JAR 文件中。
原生镜像
原生镜像的 SBOM 将使用原生可执行文件作为其主组件。
由于原生可执行文件目前未作为 Maven 构件附加到项目中,因此它们的 SBOM 也不会作为 Maven 构件附加。
与 Uber JAR 的情况一样,为原生可执行文件生成的 SBOM 中的运行时组件不包含 evidence.occurrences.location
,因为它们对应的代码和资源包含在一个原生可执行文件中。
可变 JAR
可变 JAR 发行版与快速 JAR 发行版类似,但它还包含构建时依赖项以支持应用程序的重新增强(重新构建)。
为可变 JAR 发行版生成的 SBOM 也将记录将在重新增强过程中使用的组件的位置,使用 evidence.occurrences.location
,但将其 quarkus:component:scope
属性保持为 development
。例如:
"purl" : "pkg:maven/org.apache.httpcomponents/httpcore@4.4.16?type=jar",
"properties" : [
{
"name" : "quarkus:component:scope",
"value" : "development"
}
],
"evidence" : {
"occurrences" : [
{
"location" : "lib/deployment/org.apache.httpcomponents.httpcore-4.4.16.jar"
}
]
}