Spring Boot 3.3 中的 SBOM 支持

Spring Boot 3.3.0 已经发布,其中包含对 SBOM 的支持。SBOM 是 “Software Bill of Materials”(软件物料清单)的缩写,描述了用于构建软件构件的组件。在本文中,这些组件就是你的 Spring Boot 应用。SBOM 非常有用,因为它们准确地描述了你的应用包含的内容。有了这些信息,你可以评估安全漏洞是否影响你的应用,或者使用自动化安全工具扫描你的应用程序并提醒你存在的安全漏洞。

目前有多种 SBOM 格式,使用最广泛的是 CycloneDXSPDXSyft。Spring Boot 3.3.0 开箱即支持 CycloneDX。这种支持包括以下三个方面:

  • 配置 CycloneDX 插件,以便在构建应用时生成 SBOM。
  • 将生成的 SBOM 文件打包到 uber jar 中。
  • Actuator 端点,用于显示生成的 SBOM(如果启用)。

来看看如何进行实际操作:

首先,在 start.springboot.io 上生成一个新项目(确保选择 Spring Boot 3.3.0),并添加以下依赖:

  • Spring Web
  • Actuator

然后,在 IDE 中打开生成的项目,如果使用的是 Gradle,将以下内容添加到你的 build.gradle 文件中:

plugins {
  id 'org.cyclonedx.bom' version '1.8.2'
}

这将在构建中应用 CycloneDX Gradle plugin。Spring Boot 会检测到这一点,并负责插件的配置,你无需再做任何更改。

如果使用的是 Maven,则在 pom.xml 中加入以下内容:

<plugins>
  <plugin>
    <groupId>org.cyclonedx</groupId>
    <artifactId>cyclonedx-maven-plugin</artifactId>
  </plugin>
</plugins>

这将为你的构建添加 CycloneDX Maven plugin。Spring Boot 会通过其 parent 版本自动管理该插件的版本,并负责配置该插件。

现在使用 gradle buildmvn package 构建 uber jar。在构建过程中,Spring Boot 会通过 CycloneDX 插件生成一个 SBOM,并将 SBOM 包含在 uber jar 中。如果查看一下 uber jar 的内容,就会在 META-INF/sbom/application.cdx.json 中找到 SBOM。Spring Boot 还会在 jar manifest 中添加位置(Location)和格式(Format),以便扫描工具找到它:

Sbom-Location: META-INF/sbom/application.cdx.json
Sbom-Format: CycloneDX

现在,如果你能要求正在运行的应用程序向你提供 SBOM,这样你就能清楚地知道服务器上正在运行什么,岂不美哉?

通过 Actuator 暴露 SBOM

为此,我们需要公开 SBOM Actuator 端点,而该端点默认情况下是不公开的。不过这很容易。在应用配置文件中添加以下内容:

management.endpoints.web.exposure.include=health,sbom

现在重新构建应用,并运行 jar 文件。启动完成后,就可以查询 SBOM Actuator 端点了:

curl http://localhost:8080/actuator/sbom

HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json

{"ids":["application"]}

这将返回一些 JSON 内容,其中包含所有 SBOM 的 ID。可以有多个 SBOM:一个描述应用,一个描述 JVM,一个描述操作系统,等等。默认情况下,只有一个名为 application 的 SBOM 描述你的 Spring Boot 应用。

看看 application SBOM:

curl -i http://localhost:8080/actuator/sbom/application

HTTP/1.1 200
Content-Type: application/vnd.cyclonedx+json
Content-Length: 161738

{
  "bomFormat" : "CycloneDX",
  "specVersion" : "1.5",
  "serialNumber" : "urn:uuid:3842be09-b12e-45ed-8038-babb72a53750",
  "version" : 1,
  ...

这将返回一个描述应用内容的大 JSON 文档。它包含应用所有依赖的哈希值和许可证、网站和 Issues URL 等信息。它还包含有关应用的数据,如版本号、SBOM 生成时间等。有了这些信息,你就能清楚地知道服务器上运行的是什么。以上就是 SBOM 支持的基本用法。现在我们来看看更高级的功能。

应用不同格式的 SBOM

如果你不想在自己的应用中使用 CycloneDX SBOM,而是喜欢另一种格式,你也可以这样做。不过,你必须自己配置创建 SBOM 的插件。在撰写本文时,Spring Boot 只会自动配置 CycloneDX 插件。

配置 build 以创建 SBOM 后,就可以使用 management.endpoint.sbom.application.location 属性将 Spring Boot 指向该 SBOM。如果引用的 SBOM 是 CycloneDX、SPDX 或 Syft 格式,Spring Boot 将自动检测其类型,并将其用于 Actuator 响应的 Content-Type Header。如果使用的是其他格式,则可以使用 management.endpoint.sbom.application.media-type 属性显式指定 SBOM 的媒体类型(Media Type)。

下例展示了如何使用 SPDX 格式的 SBOM:

management.endpoint.sbom.application.location=classpath:/sbom/application.spdx.json

为此,SPDX SBOM 必须存储在 src/main/resources/sbom/application.spdx.json 中。

包含额外的 SBOM

Spring Boot 支持每个应用包含多个 SBOM。如果想添加其他 SBOM,可以使用 management.endpoint.sbom.additional 下的配置属性。例如,添加名为 jvmSBOM 的操作如下:

management.endpoint.sbom.additional.jvm.location=file:/path/to/sbom.json

jvm SBOM 存储在文件系统的 /path/to/sbom.json 中。你需要自己生成这个 SBOM,或者由你的 JVM vendor 提供。

application SBOM 一样,如果引用的 SBOM 是 CycloneDX、SPDX 或 Syft 格式,Spring Boot 将自动检测其类型。否则,你可以使用以下属性自行设置媒体类型(Media Type):

management.endpoint.sbom.additional.jvm.media-type=application/json

使用此配置启动应用后,可以再次运行以下 curl 命令:

curl -i http://localhost:8080/actuator/sbom

HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json

{"ids":["application","jvm"]}

现在,端点返回两个 SBOM:applicationjvm。你可以使用 curl 命令访问 jvm SBOM:

curl -i http://localhost:8080/actuator/sbom/jvm

HTTP/1.1 200
Content-Type: application/spdx+json
Content-Length: 48739

<content of the jvm SBOM>

你可以加入任意数量的 SBOM,它们都将在 Actuator 端点上公开。

可选的 SBOM

注意,配置中引用的 SBOM 文件或资源必须存在,否则启动会失败。你可以在 SBOM 位置前加上 optional:,这表示如果文件不存在,Spring Boot 会忽略它,以防止启动失败。

总结

最后,希望你喜欢这项功能,并希望它能帮助你确保软件供应链的安全。

如果你发现任何问题,请随时访问我们的 Issues


Ref:https://spring.io/blog/2024/05/24/sbom-support-in-spring-boot-3-3